You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
При использовании виртуальных функций следует не забывать о некоторых вещах.<br />
Во-первых, статические функции-члены не могут быть объявлены виртуальными.<br />
Поскольку статические функции-члены не вызываются с объектом, никакого объекта<br />
этапа выполнения не может быть, а значит, нет и его типа.<br />
Во-вторых, при указании имени класса в вызове функция будет компилироваться<br />
с использованием раннего связывания независимо от того, объявлена она виртуальной<br />
или нет.<br />
Например, приведенный ниже вызов обращается к Base::fn(], поскольку так<br />
указал программист, независимо от того, объявлена f n () виртуальной или нет.<br />
void test (Bases b)<br />
{<br />
b.base::fn f);<br />
//Этот вызов не использует позднего связывания<br />
}<br />
Кроме того, виртуальная функция не может быть встроенной. Чтобы подставить<br />
функцию на место ее вызова, компилятор должен знать ее на этапе компиляции. Таким<br />
образом, независимо от способа описания виртуальные функции-члены рассматриваются<br />
как не встроенные.<br />
И наконец, конструкторы не могут быть виртуальными, поскольку во время работы<br />
конструктора не существует завершенного объекта какого-либо определенного типа.<br />
В момент вызова конструктора память, выделенная для объекта, является просто<br />
аморфной массой. И только после окончания работы конструктора объект становится<br />
экземпляром класса в полном смысле этого слова.<br />
В отличие от конструктора, деструктор может быть объявлен виртуальным. Более<br />
того, если он не объявлен виртуальным, вы рискуете столкнуться с неправильной ликвидацией<br />
объекта, как, например, в следующей ситуации:<br />
class Base<br />
f<br />
public:<br />
-Base () ;<br />
);<br />
class Subclass : public Base<br />
(<br />
public:<br />
-Subclass();<br />
void finishWithObject{Base* pHeapObject)<br />
{<br />
delete pHeapObject; //Здесь вызывается -Basef)<br />
//независимо от типа<br />
//указателя pHeapObject<br />
)<br />
Если указатель, передаваемый функции f inishWithObject (), на самом деле указывает<br />
на объект Subclass, деструктор Subclass все равно вызван не будет: поскольку<br />
он не был объявлен виртуальным, используется раннее связывание. Однако,<br />
если объявить деструктор виртуальным, проблема будет решена.<br />
А если вы не хотите объявлять деструктор виртуальным? Тому может быть только<br />
одна причина: виртуальные функции несколько увеличивают размер объекта. Когда<br />
программист определяет первую виртуальную функцию в классе, C++ прибавляет<br />
Глава 22. Знакомство с виртуальными функциями-членами: настоящие л