    Производный класс наследует из базового данные-члены и функции-члены, но 
не конструкторы и деструкторы. 

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


      class TDerived:   public TBase { 

    В этом случае все открытые члены TBase становятся открытыми членами в 
TDerived. Все закрытые члены TBase остаются закрытыми в своем первоначально 
объявленном классе, и в TDerived нельзя получить доступ к этим членам TBase. 

    class TDerived:   private TBase { 

    В данном случае все открытые члены TBase становятся закрытыми членами в 
TDerived. Последующие наследования TDerived не смогут получить доступ к любым 
членам TBase. Позже вы ознакомитесь с третьим типом спецификатора класса — protected. 


    TDerived():   TBase()  {   }	

объявляется конструктор производного класса TDerived() и вызывается конструктор 
базового класса с помощью специальных обозначений TBase(). Вы не можете вызвать 
конструкторы базовых классов в операторах; вы должны вызвать их, указывая их имена 
вслед за объявлением конструктора производного класса. 


   TDеrived::TDerived()  // Заголовок конструктора
      :  TBase()    // Вызов конструктора базового класса 
    {
       // В этом месте выполняются операторы конструктора 
    }



    class А {         
    public:	
       int x;	' , 
       А() { cout « "Inside A's constructor\n"; x = 0; } 
       void Display(void) { cout « "x == " « x « '\n'; }
    } ;
    Если вы хотите сделать закрытыми в производном классе только некоторые из 
наследуемых членов, можно выборочно квалифицировать один или несколько из них. 
Предположим, вы хотите, чтобы открытый в А целочисленный член х стал закрытым 
в В, а открытая в А функция Display() осталась бы открытой в В так, чтобы 
внешние операторы могли ее вызывать. Для этого укажите базовый класс А 
закрытым в В, как это уже делалось ранее, а в открытой секции В квалифицируйте 
наследуемые члены, которые вы хотели бы оставить открытыми: 
    class В:   private А {	
    public:
      A::Display;               // Выборочное уточнение Display()
      В(): 
      А() { cout « "Inside B's constructor";   }                      
    }  
    Выражение A::Display; в открытой секции класса В указывает компилятору, 
что этот член, объявленный в классе А, должен остаться открытым. Наследуемый 
целочисленный член х станет закрытым членом класса В, как и прежде, однако 
функция-член Display() останется открытой. Предыдущая попытка вызова Display()
для объекта класса В теперь скомпилируется и выполнится правильно: 


    В отличие от конструкторов, деструктор производного класса никогда не 
вызывает непосредственно деструктор базового класса. (Конечно, можно вызвать в 
программе деструктор как обычную функцию-член. См. главу 15.) C++ 


Поскольку она идентична члену Display() базового класса, то замещает наследованную.


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


    Статические функции-члены описаны в главе 15. А пока не обращайте внимания 
на статическую; функцию-член resolution() в классе TTimer.	


    Для лучшего понимания виртуальных функций сперва ознакомьтесь с важным 
принципом классов C++, связанных отношением наследования. Согласно правилам 
C++ указатель на базовый класс может ссылаться на объект этого класса или на 
объект любого другого класса, производного от базового (рис. 14.10 и 14.11). 


    В данном случае употреблять ключевое слово virtual не обязательно, 
поскольку С находится в конце линии наследования. Конечно, если еще один класс 
D будет выведен из класса С и в D потребуется заместить функцию vf(), то в С эта 
функция должна быть определена с ключевым словом virtual. Будьте готовы сейчас 


   21:   	TValue *basep;
   22:
   23:	basep = new TValue(10);   
   24:	cout « basep->GetValue() «  '\n';    // Выведет 10 
   25:	delete basep; 
   26:	 
   27:	basep = new TMult(10,  2);         .   // !!! 
   28:	cout « basep->GetValue() « '\n';    // !!! Выведет 20 
   29:	delete basep;

    TBase *pbase; 
    pbase = new TDerived("String 1",  "String 2"); 

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


Конечно, вы можете удалитьключевое слово virtual в последнем из производных 
классов в линии наследования. 


     Объявляется чистая виртуальная функция точно так же, как и обычная, только 
ее объявление в классе завершается  = 0. Например, в классе 
   class AbstractClass    {  
   public: 
      virtual void f1(void);         // Обычная виртуальная функция-член 
      virtual void f2(void) = 0;  // Чистая виртуальная функция-член 
    } 


     Конечно, другие функции-члены класса AbstractClass могут вызывать чистую виртуальную 
функцию-член.


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

    Выполнение оператора	
    myObject.f1 ();	
    приведет к вызову наследованной f1(), которая вызовет f2() из MyClass.	: 


Как показано в строке 6, C++ позволяет делать неполные объявления классов, не имеющих 
тела: 
    class TElem;   // Неполное объявление класса	


    Функции-члены и деструкторы, но не конструкторы, могут быть виртуальными. 
    Конечно, если деструкторы не виртуальные, вызовется только деструктор базового класса, 
оставив вторую копию строки в памяти, что может послу жить причиной серьезной ошибки.

    class D:  public A,  public В { 
    public: 
         void f(void); 
         .......
     };
    в функции-члене f() необходимо указать, какую из конфликтующих функций 
Display() следует вызвать. Нужного эффекта можно добиться, задав имя 
соответствующего класса и оператора разрешения области видимости перед вызовом 
функции:
   void D::f( void )
   { 
       Display();      // ??? Двусмысленно; не скомпилируется 
       А::Display() ;    // Вызов функции-члена А 
       В::Display() ;    // Вызов функции-члена В 
   }
    

    сlass D:  public A,  public В,  public С { 
    public:
       D():  А(),   В(),   с()  {  }	// Встраиваемый конструктор 
       ........
     };
    Или же конструктор можно объявить как 
    class D:   public A,   public В,   public С { 
    public: 
        D() ;	// Конструктор,  реализованный снаружи 
        ......
    }; 
    и реализовать отдельно, обычно, в другом файле: 
    D::D() 
       :  А(),   В(),   С() 
    {	
        ... // Операторы в конструкторе D() 
    }


    При отладке вашего собственного кода вы можете использовать операторы 
отображения, подобные тем, что использовались в FRANCH.CPP. Отображение 
сообщений из конструкторов, деструкторов или функций-членов — полезная обратная 
связь с сложной иерархической организацией классов. 


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

    Класс Company не изменился, в то время как в Jennys, McDougles, 
BurgerQuen, Bob, Ted и Alice, конечно, потребовались изменения для 
предупреждения в будущем наследования нескольких копий их базового 
класса-родителя. Например, Bob теперь объявлен следующим образом: 

    class Bob 
    : virtual public Jennys,	
       virtual public McDougles { 

добавление ключевого слова virtual к перечисленным базовым классам 
указывает компилятору, что в последующих выводах классов, также наследующих Jennis или 
McDougies, должна существовать только одна копия этих двух базовых классов. 
Аналогично, в классах Ted и Alice (строки 43-52) базовые классы указаны виртуальными. 
    Теперь можно спроектировать класс Corporation (строки 54-64). Как и ранее, 
класс наследует базовые McDougies, Ted и Alice. Койечно, с объявлением 
McDougies виртуальным базовым классом в итоге будет существовать только одна копия 
класса Corporation, несмотря на то, что Ted и Alice также выведены из класса McDougies. 
