Выбрать главу

    protected :

        House* pHouse ;

    } ;

    class LittlePig : public Pig

    {

    public :

        LittlePig( float volStraw , int numSticks , int numBricks )

            : straw( volStraw ) , sticks( numSticks ) , bricks( numBricks )

        { }

    protected :

        float straw ;

        int sticks ;

        int bricks ;

    } ;

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

_________________

237 стр. Глава 20. Наследование классов

Деструкция подкласса...238

Следуя правилу о том, что деструкторы вызываются в порядке, обратном вызову конструкторов, первым вызывается деструктор GraduateStudent. После того как он выполнит свою работу, управление передаётся деструктору класса Advisor, а затем деструктору Student. Если бы Student был наследником класса Person, его деструктор получил бы управление после деструктора Student.

И это логично. Блок памяти сначала преобразуется в объект Student, а уже затем конструктор для GraduateStudent превращает этого студента в аспиранта. Деструктор же просто выполняет этот процесс в обратном направлении.

►Отношение СОДЕРЖИТ...238

Обратите внимание, что класс GraduateStudent включает в себя члены классов Student и Advisor, однако он включает их по-разному. Определяя данные-члены класса Advisor, вы знаете, что класс Student содержит внутри все данные-члены класса Advisor, но вы не можете сказать, что GraduateStudent ЯВЛЯЕТСЯ Advisor. Однако вы можете сказать, что GraduateStudent СОДЕРЖИТ Advisor. Какая разница между этим отношением и наследованием?

Используем в качестве примера автомобиль. Вы можете логически определить автомобиль как подкласс транспортных средств, а значит, он будет наследовать свойства остальных транспортных средств. С другой стороны, автомобиль содержит мотор. Если вы покупаете автомобиль, то покупаете и мотор ( если, конечно, вы не покупаете бывшую в употреблении машину там же, где я купил свою кучу металлолома ).

Если друзья пригласят вас приехать на воскресный пикник на новой машине и вы приедете на ней, никто не будет удивлён ( даже если вы явитесь на мотоцикле ), поскольку автомобиль ЯВЛЯЕТСЯ транспортным средством. Но если вы появитесь на своих двоих, неся в руках мотор, друзья решат, что вы попросту издеваетесь над ними, поскольку мотор не является транспортным средством, так как не имеет некоторых важных свойств, присущих транспортным средствам.

В аспекте программирования связь типа СОДЕРЖИТ достаточно очевидна. Разберём следующий пример:

    class Vehicle

    {

    } ;

    class Motor

    {

    } ;

    class Car : public Vehicle

    {

    public :

        Motor motor ;

    } ;

    void VehicleFn( Vehicle& v ) ;

    void motorFn( Motor& m ) ;

_________________

238 стр. Часть 4. Наследование

    int main( )

    {

        Car с ;

        VehicleFn( с ) ; /* Так можно вызвать */

        motorFn( c ) ; /* А так — нельзя */

        motorFn( с.motor ) ; /* Нужно вот так */

        return 0 ;

    }

Вызов VehicleFn( с ) допустим, поскольку с ЯВЛЯЕТСЯ Vehicle. Вызов motorFn( с ) недопустим, поскольку с — не Motor, хотя он и содержит Motor. Если возникает необходимость передать функции только ту часть с, которая является мотором, это следует выразить явно: motorFn( с.motor ).

_________________

239 стр. Глава 20. Наследование классов

Глава 21. ЗНАКОМСТВО С ВИРТУАЛЬНЫМИ ФУНКЦИЯМИ-ЧЛЕНАМИ: НАСТОЯЩИЕ ЛИ ОНИ...240

ОГЛАВЛЕНИЕ

        В этой главе...

►Зачем нужен полиморфизм 243