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

        system( "PAUSE" ) ; return 0 ;

    }

В этой программе продемонстрировано создание и использование двух объектов — Student и GraduateStudent. Вывод программы выглядит следующим образом.

    Конструктор Student Су N Sense

    Конструктор Student Matt Madox

    Конструктор GraduateStudent Matt Madox

    Добавляем оценку для Су N Sense

    Добавляем оценку для Matt Madox

    Оценка Matt = 1.5

    Press any key to continue...

Использование подкласса...236

Класс Student определён как обычно. Определение класса GraduateStudent несколько отличается — наличием после имени класса двоеточия с последующим public Student. Тем самым класс GraduateStudent объявляется как подкласс класса Student.

«Ключевое слово public говорит о том, что может быть наследование protected, а также private — но эти вопросы лежат за пределами данной книги.»

[Советы]

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

■■■

■ GraduateStudent — подкласс Student;

■ Student — базовый, или родительский класс для GraduateStudent;

■ GraduateStudent наследует Student;

■ GraduateStudent расширяет Student.

■■■

_________________

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

В качестве подкласса Student класс GraduateStudent наследует все его члены. Например, GraduateStudent имеет член name, хотя он объявлен в базовом классе. Однако подкласс может добавлять собственные члены, например, qualifierGrade.

Функция main( ) объявляет два объекта, типа Student и GraduateStudent, после чего вызывает функцию addCourse( ) для каждого из них, а потом — функцию qualifier( ), которая имеется только у подкласса.

Конструирование подкласса...237

Хотя подкласс и имеет доступ к защищённым членам базового класса, а значит, может инициализировать их, было бы хорошо, если бы базовый класс всё же конструировал сам себя. В действительности так и происходит.

Перед тем как управление получает код, стоящий за открывающей фигурной скобкой класса GraduateStudent, оно передаётся конструктору по умолчанию класса Student ( поскольку другой конструктор не был указан ). Если бы класс Student был наследником другого класса, например Person, то конструктор этого класса вызывался бы до передачи управления конструктору Student. Подобно небоскребу, объект строится, начиная с "фундаментального" уровня в соответствии со структурой наследования классов и вызывая конструкторы всех классов, составляющих данный.

Как и в случае с объектами-членами, вам может понадобиться передавать аргументы конструктору базового класса. Это делается почти так же, как и изученная ранее передача аргументов конструктору объекта-члена ( смотрите приведённый ниже пример ).

    GraduateStudent( char *pName , Advisor&adv , float qG=0.0 )

        :Student( pName ) , advisor( adv ) , qualifierGrade(qG)

    {

        /* Код конструктора */

    }

В этом примере конструктор класса GraduateStudent вызывает конструктор Student, передавая ему аргумент pName. Базовый класс конструируется до любых объектов-членов, а значит, конструктор класса Student вызывается перед конструктором Advisor. И только после конструктора члена Advisor начинает работу конструктор GraduateStudent.

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

    class Pig

    {

    public :

        Pig( ) : pHouse( 0 ) { }