    picture[]= new	Circle;
    picture[]	= new	Circle; 
    picture[]	= new	Line; 
    picture[]	= new	Circle; 
    picture[]= new        Line; 

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

    Виртуальные и невиртуальные функции-члены 

    Рассмотрим еще один простой класс, в котором объявляются данные-члены, 
конструктор и функция-член, имея при этом в виду правила использования 
указателей на классы, изложенные в предыдущем разделе: 

    class TValue { 
    protected: 
       int value;	
       TValuefint n) { value = n;  }	
       int GetValue(void) { return value;  } 
   }; 

    Вы можете объявить и использовать объект типа TValue, сохраняющий и 
возвращающий по требованию целочисленное значение:	

    Tvalue х(10);	// Инициализировать объект Tvalue x 
    cout « x.GetValue() « '\n';                 // Выведет 10 

    Затем выведите новый класс из TValue. Для демонстрации возможностей 
производный класс умножает значение базового класса на заданное значение. 
Давайте назовем этот класс TMult: 

    class TMult:   public TValue { 
    protected: 
       int multiplier;	
    public: 
       TMult(int n,  int m):  TValue(n) { multiplier = m;   } 
        int GetValue(void) { return value * multiplier;   } 

    В TMult наследованная им функция-член GetValueO замещается новой функцией, 
возвращающей value * multiplier. Если вы объявите объект типа TMult и вызовете 
его функцию-член GetValue(), результатом будет, как вы могли ожидать, 
произведение двух значений, которыми был инициализирован объект. 

    TMult y(10,  2);	// Инициализировать объект TMult у                        
     cout « у.GetValueO « '\n';                 // Выведет 20                                                                     

    Посмотрим, .что произойдет, если вы используете указатель на объект типа 
TSingle или TDouble. Вы можете объявить и инициализировать указатель tvp типа 
TValue следующим образом: 

    TValue *tvp = new TValue(10); 

    Затем можете вызвать функцию-член GetValueO для объекта, на который 
ссылается указатель: 

    cout « tvp->GetValue() « '\n';	// Выведет 20 

    Конечно, вы также можете объявить указатель на производный класс TMult и 
вызвать замещающую функцию-член GetValue(): 

    TMult *tmp = new Tf -t(10,  2); 
    cout « tmp->GetValue() « '\n';	// Выведет 20 

    Применив правило C++, касающееся указателей и производных классов, вы 
также можете объявить указатель на базовый класс 

    TValue «basep;	// Указатель на объект TValue 

и затем присвоить адрес производного объекта этому указателю: 

    basep = new TMult(10, 2);         // !!! Адрес производного объекта 

    Указатель basep был объявлен для ссылок на объекты класса TValue, однако в 
данном операторе создается производный объект TMult, а его адрес присваивается 
basep. Как вы думаете, что произойдет при выполнении ледующего оператора: 

    cout « basep->GetValue() « '\г\';         // ??? Выведет 10 

    Этот оператор скомпилируется, однако не даст ожидаемого результата — 20. 
Как известно, в C++ указатель basep ссылается на объект TValue. 
Следовательно, C++ вызывает функцию-член GetValueO из базового 


    Глава 14. Объектно-ориентированное программирование 353 
    Освоение Borland® C++4.5 
