в виду главным образом способность
и динамического связывания.
Когда мы говорим о полиморфизме в языке C++, то имеем в виду главным образом способность указателя или ссылки на базовый класс адресовать любой из производных от него. Если определить обычную функцию eval() следующим образом:
// pquery может адресовать любой из классов, производных от Query
void eval( const Query *pquery )
{
pquery->eval();
}
то мы вправе вызывать ее, передавая адрес объекта любого из четырех типов запросов:
int main()
{
AndQuery aq;
NotQuery notq;
OrQuery *oq = new OrQuery;
NameQuery nq( "Botticelli" );
// правильно: любой производный от Query класс
// компилятор автоматически преобразует в базовый класс
eval( &aq );
eval( ¬q );
eval( oq );
eval( &nq );
}
В то же время попытка передать eval() адрес объекта класса, не являющегося производным от Query, вызовет ошибку компиляции:
int main()
{
string name( "Scooby-Doo" );
// ошибка: тип string не является производным от Query
eval( &name );
}
Внутри eval() выполнение инструкции вида
pquery->eval();
должно вызывать нужную виртуальную функцию-член eval() в зависимости от фактического класса объекта, адресуемого указателем pquery. В примере выше pquery последовательно адресует объекты AndQuery, NotQuery, OrQuery и NameQuery. В каждой точке вызова определяется фактический тип класса объекта и вызывается подходящий экземпляр eval().
Механизм, с помощью которого это достигается, называется динамическим связыванием. (Мы вернемся к проектированию и использованию виртуальных функций в разделе 17.5.)
В объектно-ориентированной парадигме программист манипулирует неизвестным экземпляром, принадлежащим к одному из ограниченного, но потенциально бесконечного множества различных типов. (Ограничено оно иерархией наследования. Теоретически, однако, ни на глубину, ни на ширину такой иерархии не накладывается никаких ограничений.) В C++ это достигается путем манипулирования объектами исключительно через указатели и ссылки на базовый класс. В объектной (не объектно-ориентированной) парадигме программист работает с экземпляром фиксированного типа, который полностью определен на этапе компиляции.
Содержание Назад Вперед