Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
50
Добавлен:
16.02.2016
Размер:
196.61 Кб
Скачать

Int GetX(){return X;}

Int GetY(){return y;}

void SetX(int _x){x = _x;}

void SetY(int _y){y = _y;}

};

class OutCoord: public Coord

{

public:

OutCoord(int _x, int _y): Coord(_x, _y){}

Void ShowX(){cout « GetX() « ' ' ;}

Void ShowY(){cout « GetY()« ' ';}

};

main ()

{

OutCoord* ptr;

ptr = new OutCoord(10,20); //Создание объекта a кучe

ptr->ShowX();

ptr->ShowY();

cout « "\n";

delete ptr; //Удаление объекта из кучи

return 0;

}

Здесь класс OutCoord является производным от базового класса Coord. К членам класса Coord он добавляет две откры­тые функции и конструктор. Напомним, что конструкторы не наследуются. Поэтому производный класс либо должен объявить свой конструктор, либо предоставить возможность компилятору сгенерировать конструктор по умолчанию. Правила, действую­щие в отношении конструкторов по умолчанию, были нами из­ложены выше.

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

<констр_произв_класса> (<список параметров>):

<констр_базового_класса> (<cписок_apг>)

{<тело_конструктора>)

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

В приведенном выше примере эта конструкция использована для создания конструктора класса OutCord. В данном случае конструктор имеет вид:

OutCoord(int _x, int _y): Coord(_x, _y){}

Тело конструктора оставлено пустым, так как класс OutCoord не имеет собственных данных-членов. Все параметры конструктора производного класса просто переданы конструкто­ру базового класса для осуществления инициализации. Аргумен­ты конструктору производного класса передаются в операторе new, который неявно вызывает этот конструктор. Затем про­грамма вызывает функции-члены ShowX () и ShowY () объекта, являющегося представителем производного класса, которые вы­водят на экран в одной строке заданные значения координат. Наконец, оператор delete вызывает удаление объекта, для чего он неявно вызывает деструктор производного класса.

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

Хотя конструктор базового класса и наследуется, вызывается он только компилятором, когда конструируется объект производ­ного класса. Конструктор, в отличие от других унаследованных функций, вызвать явно нельзя.

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

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

#include <iostream.h>

class Base

{

public:

Base()

{

cout « "Мы в конструкторе "« "базового класса" « "\n";

}

~Base ()

{

cout « "Мы в деструкторе базового” « "класса" « "\n";

}

};

class Derived: public Base

{

public:

Derived()

{

cout « "Мы в конструкторе производного класса" « "\n";

}

~Derived ()

{

cout «"Мы в деструкторе производного класса" « "\n";

}

};

main()

{

Derived ob;

return 0;

}

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

Мы в конструкторе базового класса

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

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

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

Для дальнейшего очень важно понимать работу конструкто­ров и деструкторов при наследовании.

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

Модифицируем рассмотренный нами пример так, чтобы про­изводный класс переопределял функции-члены своего базового класса GetX() nGetY():

#include <iostream.h>

class Coord

{

protected:

int x, y;

public:

Coord(int _x, int _y) {x = _x; у = _y;}

Coord() {x = 0; у = 0;}

Соседние файлы в папке ЛекцииКарасева