Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ООП Лекции PDF / ООП 05 Лек Простое наследование.pdf
Скачиваний:
57
Добавлен:
15.02.2015
Размер:
288.68 Кб
Скачать

Лекция 5

Простое наследование

1

Л Е К Ц И Я 5

ПРОСТОЕ НАСЛЕДОВАНИЕ _____________________________________________________________ 1

Работа конструктора и деструктора ________________________________________________________ 2 Базовый класс координат ________________________________________________________________ 2 Производный класс точки ________________________________________________________________ 3 Производный класс вектора ______________________________________________________________ 4 Использование конструктора с параметрами ________________________________________________ 6 Переопределение и вызов членов базового класса___________________________________________ 6

ПРОСТОЕ НАСЛЕДОВАНИЕ

Язык C++ позволяет классу наследовать данные-члены и функции-члены одного или нескольких других классов. При этом новый класс называют производным классом (или классом-потомком). Класс, эле-

менты которого наследуются, называется базовым классом (родительским классом или классом-

предком) для своего производного класса. Наследование дает возможность некоторые общие черты поведения классов абстрагировать в одном базовом классе.

Производные классы могут:

содержать новые данные-члены и функции-члены; видоизменять некоторые функции-члены базового класса.

Таким образом, определение производного класса значительно сокращается, поскольку нужно определить только отличающие его от производных классов черты поведения.

Синтаксис объявления производного класса имеет следующий вид:

class Basel

 

// Базовый класс

{ <элементы_класса>

} ;

 

class Base2

 

// Базовый класс

{ <элементы_класса>

} ;

 

class Derived : <спецификатор_доступа> Basel ,

// Производный класс

<спецификатор_доступа> Base2 ,

 

• • •

 

<спецификатор_доступа> BaseN

 

{ <элементы_класса>

} ;

 

Здесь <спецификатор_доступа> – это public, protected или private; он не является обязательным и по умолчанию принимает значение private для классов и public для структур. Спецификатор доступа при наследовании определяет уровень доступа к элементам базового класса, который получают элементы производного класса. В приведенной ниже таблице описаны возможные варианты наследуемого доступа.

Доступ в производном классе

 

 

Доступ в базовом классе

 

 

public

protected

 

private

Спецификатор наследуемого доступа

 

 

 

 

 

public

public

protected

 

недоступны

 

 

 

 

 

private

private

private

 

недоступны

 

protected

protected

protected

 

недоступны

 

 

 

 

 

 

Изучение таблицы показывает, что спецификатор наследуемого доступа устанавливает тот уровень доступа, до которого понижается уровень доступа к членам, установленный в базовом классе. Из этого правила можно сделать исключения. Если спецификатор наследуемого доступа установлен как private, то public-члены базового класса будут являться private-членами в производном классе. Однако можно сделать некоторые из членов базового класса открытыми в производном классе, объявив их в секции public производного класса.

Таким образом, при таком наследовании открытые и защищенные члены базового класса будут доступны только для членов данного производного класса, и все члены базового класса, кроме явно объявленных в разделе public или protected, будут закрытыми для следующих производных классов. Этот при-

Выжол Ю.А.

Объектно-ориентированное программирование

Лекция 5

Простое наследование

2

ем позволяет отсечь доступ к членам базового класса при построении иерархии классов с отношением родитель – потомок.

Напомним, что при любом способе наследования в производном классе доступны только открытые ( public ) и защищенные ( protected ) члены базового класса (хотя наследуются все члены базового класса). Иначе говоря, закрытые члены базового класса остаются закрытыми, независимо от того, как этот класс наследуется.

Производный класс наследует не все члены базового класса. Перечислим ненаследуемые члены класса:

конструкторы; конструкторы копирования; деструкторы;

перегруженные операторы присвоения; друзья класса.

Работа конструктора и деструктора

Чтобы более наглядно изучить работу конструкторов и деструкторов базового и производного классов, рассмотрим следующий пример:

class Coord

 

 

// базовый класс

{

 

 

 

public :

 

 

 

Coord ( )

{ cout <<"Constructor Coord \n"; }

// конструктор базового класса

~Coord ( ) { cout <<"Destructor Coord \n";

}

// деструктор базового класса

}

 

 

 

class Dot : public Coord

 

// производный класс – наследник класса Coord

{

 

 

 

public :

 

 

 

Dot ( )

{ cout <<"Constructor Dot \n";

}

// конструктор производного класса

~Dot ( )

{ cout <<"Destructor Dot \n";

}

// деструктор производного класса

}

 

 

 

void main ( )

 

 

 

{

 

 

 

Dot A ;

 

 

// создание объекта производного класса

}

 

 

 

Эта программа выводит на экран следующее:

Constructor Coord Constructor Dot Destructor Dot Destructor Coord

При создании экземпляра производного класса автоматически вызывается конструктор базового класса. После того как объект создан, конструктор базового класса становится недоступным. Хотя конструктор базового класса не наследуется, он вызывается только компилятором при конструировании объект производного класса. Конструктор базового класса вызвать явно нельзя.

В отношении деструкторов производных классов также действуют определенные правила. Деструктор производного класса должен выполняться раньше деструктора базового класса (иначе деструктор базового класса мог бы разрушить данные-члены, которые используются и в производном классе). Когда деструктор производного класса выполнит свою часть работы по уничтожению объекта, вызывается деструктор базового класса. Причем вся работа по организации соответствующего вызова возлагается на компилятор и программист не должен заботиться об этом.

Базовый класс координат

В предыдущей лекции мы создали два класса: класс точки Dot и класс вектора Vec. У этих классов существуют идентичные данные-члены x и y, идентичные функции-члены GetX ( ) и GetY ( ), а также похожие функции-члены Print ( ) и Input ( ). В данной задаче целесообразно создать абстрактный базовый класс Coord, который будет содержать общие черты поведения класса Dot и класса Vec.

#include <iostream.h> #include <windows.h> #include <math.h>

Выжол Ю.А.

Объектно-ориентированное программирование

Лекция 5

Простое наследование

3

class Coord

// базовый класс координат

 

{

 

 

protected:

// защищённые члены класса, доступны только классам-потомкам

 

double x , y ;

// координаты

 

double Hypotenuse ( ) { return sqrt ( x*x + y*y ) ; } // возвращает расстояние между

 

public :

// текущей точкой и началом координат

 

// конструкторы класса, потомками не наследуются

 

Coord ( )

{ x = 0 ; y = 0 ; } // инициализирует координаты нулями

 

Coord ( double X , double Y ) { x = X ; y = Y ; } // инициализирует координаты заданными значениями // функции-члены класса, наследуются потомками

void Print ( ) ;

 

 

// выводит на экран значения координат

void Input ( ) ;

 

 

// вводит значения координат с клавиатуры

inline double GetX ( ) const

{

return x ;

} // возвращает координату x

inline double GetY ( ) const

{

return y ;

} // возвращает координату y

inline void SetX ( double X )

{

x = X ;

} // передаёт заданное значение в координату x

inline void SetY ( double Y )

{

y = Y ;

} // передаёт заданное значение в координату y

} ;

 

 

 

// функция-член класса Coord позволяет выводить значения координат на экран

void Coord :: Print ( )

 

 

 

{

 

 

 

cout <<"\tx="<<x<<"\ty="<<y<<’\n’ ;

// выводит на экран значения координат с подписями

}

// функция-член класса Coord позволяет вводить значения координат с помощью клавиатуры void Coord :: Input ( )

{

cout <<"\tx=";

cin>>x ; // выводит на экран приглашение “x=” и вводит значения x с клавиатуры

cout <<"\ty=";

cin>>y ; // выводит на экран приглашение “y=” и вводит значения y с клавиатуры

}

Базовый класс Coord содержит данные-члены x, y и два конструктора. Конструктор класса Coord( ) параметров не имеет и инициализирует данные-члены нулями. Конструктор класса Coord( double X , double Y) позволяет инициализировать данные-члены заданными значениями.

Функция-член класса Print( ) позволяет выводить на экран значения данных-членов в виде:

x = 5

y = 6

Функция-член класса Input( ) позволяет выводить на экран приглашение и вводить значения данныхчленов с клавиатуры в виде:

x = 5 y = 6

Функции-члены класса GetX( ) и GetY( ) позволяет возвращать в место вызова значения данныхчленов x и y соответственно. Эти функции пригодятся нам в том случае, когда нам потребуются значения закрытых (private) данных-членов за пределами класса, в котором они объявлены.

Производный класс точки

Если у производного класса имеется всего один базовый класс, то говорят о простом наследовании. Следующий пример иллюстрирует простое наследование.

#include ”Coord.h”

class Dot : public Coord // производный класс Dot наследует элементы базового класса Coord

{

char name ;

// имя точки

 

public :

 

 

// конструкторы производного класса

 

Dot ( char Name ) :

Coord ( )

{ name = Name ; }

Dot ( char Name , double X , double Y ) : Coord ( X , Y ){ name = Name ; }

// переопределённые функции-члены

 

void Input ( ) ;

// выводит приглашение и вводит координаты текущей точки с клавиатуры

void Print ( ) ;

// выводит на экран имя и координаты текущей точки

double Dist ( Dot A ) ; // возвращает расстояние между текущей и заданной точками

} ;

 

 

// член класса Dot выводит на экран заголовок, имя точки и значения координат текущей точки

void Dot :: Print ( )

 

 

Выжол Ю.А.

 

Объектно-ориентированное программирование