Производный класс сам может быть базовым классом. Например:
class employee {... }; class secretary: employee {... }; class manager: employee {... }; class temporary: employee {... }; class consultant: temporary {... }; class director: manager {... }; class vice_president: manager {... }; class president: vice_president {... };Такое множество родственных классов принято называть иерархией классов. Поскольку можно выводить класс только из одного базового класса, такая иерархия является деревом и не может быть графом более общей структуры. Например:
class temporary {... }; class employee {... }; class secretary: employee {... }; // не C++: class temporary_secretary: temporary: secretary {... }; class consultant: temporary: employee {... };И этот факт вызывает сожаление, потому что направленный ациклический граф производных классов был бы очень полезен. Такие структуры описать нельзя, но можно смоделировать с помощью членов соответствующий типов. Например:
class temporary {... }; class employee {... }; class secretary: employee {... }; // Альтернатива: class temporary_secretary: secretary { temporary temp;... }; class consultant: employee { temporary temp;... };Это выглядит неэлегантно и страдает как раз от тех проблем, для преодоления которых были изобретены производные классы. Например, поскольку consultant не является производным от temporary, consultant'а нельзя помещать с список временных служащих (temporary employee), не написав специальной программы. Однако во многих полезных программах этот метод успешно используется.
|
|
Конструкторы и Деструкторы
Для некоторых производных классов нужны конструкторы. Если у базового класса есть конструктор, он должен вызываться, и если для этого конструктора нужны параметры, их надо предоставить. Например:
class base { //... public: base(char* n, short t); ~base(); }; class derived: public base { base m; public: derived(char* n); ~derived(); };Параметры конструктора базового класса специфицируются в определении конструктора производного класса. В этом смысле базовый класс работает точно также, как неименованный член производного класса (см. #5.5.4). Например:
derived::derived(char* n): (n,10), m("member",123) { //... }Объекты класса конструируются снизу вверх: сначала базовый, потом члены, а потом сам производный класс. Уничтожаются они в обратном порядке: сначала сам производный класс, потом члены а потом базовый.