#include
using namespace std;
class FishDummyMember
{
public:
FishDummyMember ()
{
cout « "FishDummyMember constructor" « endl;
}
.1: -FishDummyMember()
-I: {
cout « "FishDummyMember destructor" « endl;
-5: };
class Fish
-3: {
3 6: protected:
FishDummyMember dummy;
public:
// Конструктор класса Fish
3 4: Fish()
:=: {
36: cout « "Fish constructor" « endl;
3~: }
-Fish()
264 ЗАНЯТИЕ 10. Реализация наследования
{
cout « "Fish destructor" « endl;
}
};
34:
class TunaDummyMember
{
public:
TunaDummyMember()
{
cout « "TunaDummyMember constructor" « endl;
}
42:
-TunaDummyMember()
{
cout « "TunaDummyMember destructor" « endl;
}
};
48:
49:
class Tuna: public Fish
{
private:
TunaDummyMember dummy;
public:
Tuna()
{
cout « "Tuna constructor" « endl;
}
-Tuna()
{
cout « "Tuna destructor" « endl;
}
64:
};
6 6 :
int main()
{
Tuna myDinner;
}
Результат
FishDummyMember constructor
Fish constructor
TunaDummyMember constructor
Tuna constructor
Tuna destructor
TunaDummyMember destructor
Fish destructor
FishDummyMember destructor
Закрытое наследование
|
265
|
Анализ
Функция m ain (), представленная в строках 67 -70, поразительно мала для объема создаваемого ею вывода. Создания экземпляра класса T una достаточно для этих строк вывода, поскольку операторы с o u t вставлены в конструкторы и деструкторы всех задей ствованных объектов. Для демонстрации создания и удаления переменных определены два вымышленных класса, FishDummyMember и TunaDummyMember, с операторами c o u t
конструкторах и деструкторах. Классы F is h и Tuna содержат члены для каждого из этих вымышленных классов (строки 20 и 53). Вывод указывает, что создание объекта класса Tuna фактически начинается сверху иерархии. Так, часть базового класса F is h в составе класса Tuna создается первой, при этом такие его члены, как F i s h : : dummy, создаются сначала. Далее следует конструктор класса F is h , который естественно выполняется после создания таких атрибутов, как dummy. После создания экземпляра базового класса созда ние экземпляра Tuna продолжается созданием экземпляра T u n a : : dummy и завершается выполнением кода конструктора T u n a : : Tuna (). Вывод демонстрирует, что последова тельность удаления прямо противоположна.
Закрытое наследование
Закрытое наследование (private inheritance) отличается от открытого (которое рассма тривалось до сих пор) тем, что в строке объявления производного класса как происходя щего от базового класса используется ключевое слово p r i v a t e :
class Base
{
// ... переменные-члены и методы базового класса
};
class Derived: private Base // закрытое наследование
{
// ... переменные-члены и методы производного класса
};
Закрытое наследование базового класса означает, что все открытые члены и атрибуты базового класса являются закрытыми (т.е. недоступными) для всех, кроме экземпляра про изводного класса. Другими словами, даже открытые члены и методы класса B ase могут быть использованы только классом D e riv e d , но ни кем-либо, еще владеющим экземпля ром класса D eriv e d .
Это резко контрастирует с примерами класса Tuna и его базового класса F is h , ко торые мы рассматривали начиная с листинга 10.1. Ф ункция m a i n ( ) в листинге 10.1 может вызвать функцию F i s h : :Swim() у экземпляра класса Tuna, поскольку функция Гi s h : : Swim () является открытым методом и потому, что класс Tuna происходит от клас са F is h с использованием открытого наследования. Попробуйте переименовать ключевое слово p u b l i c на p r i v a t e в строке 17, и вы получите сбой компиляции.
Таким образом, для мира вне иерархии наследования закрытое наследование по суще ству не означает отношение есть (is-a) (вообразите тунца, который не может плавать!). Поскольку закрытое наследование позволяет использовать атрибуты и методы базового класса только производным классам, которые происходят от него, создаются отношения,
266 ЗАНЯТИЕ 10. Реализация наследования
Do'stlaringiz bilan baham: |