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



         

Объектно-ориентированное проектирование - часть 2


и динамического связывания.

Когда мы говорим о полиморфизме в языке 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( &notq );

   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++ это достигается путем манипулирования объектами исключительно через указатели и ссылки на базовый класс. В объектной (не объектно-ориентированной) парадигме программист работает с экземпляром фиксированного типа, который полностью определен на этапе компиляции.




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