С++ для начинающих



         

Доступ к членам базового класса - часть 5


pb->eval();  // вызывается NameQuery::eval()

вызывается функция из NameQuery. За исключением вызова виртуальной функции, объявленной в Query и переопределенной в NameQuery, другого способа напрямую добраться до членов класса NameQuery через указатель pb не существует:

a)    если в Query и NameQuery объявлены некоторые невиртуальные функции-члены с одинаковым именем, то через pb всегда вызывается экземпляр из Query;

b)   если в Query и NameQuery объявлены одноименные члены, то через pb обращение происходит к члену класса Query;

c)    если в NameQuery имеется виртуальная функция, отсутствующая в Query, скажем suffix(), то попытка вызвать ее через pb приводит к ошибке компиляции:

// ошибка: suffix() - не член класса Query

pb->suffix();

Обращение к члену или невиртуальной функции-члену класса NameQuery через pb тоже вызывает ошибку компиляции:

// ошибка: _name - не член класса Query

pb->_name;

Квалификация имени члена в этом случае не помогает:

// ошибка: у класса Query нет базового класса NameQuery

pb->NameQuery::_name;

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

Такой подход может показаться недостаточно гибким, но у него есть два весомых преимущества:

  • поиск виртуальной функции-члена во время выполнения никогда не закончится неудачно из-за того, что фактический тип класса не существует. В таком случае программа просто не смогла бы откомпилироваться;
  • механизм виртуализации можно оптимизировать. Часто вызов такой функции оказывается не дороже, чем косвенный вызов функции по указателю (детально этот вопрос рассмотрен в [LIPPMAN96a]).



  • Содержание  Назад  Вперед