Стандарты программирования на С++. 101 правило и рекомендация | страница 114



Статический полиморфизм посредством шаблонов также позволяет значению иметь несколько типов. Внутри шаблона

>template void f(T t) { /* ... */ }

>t может иметь любой тип, который можно подставить в >f для получения компилируемого кода. Это называется "неявным интерфейсом" в противоположность явному интерфейсу базового класса. Таким образом достигается та же цель полиморфизма — написание кода, который работает с разными типами — но совершенно иным путем.

Статический полиморфизм наилучшим образом подходит для решения следующих задач.

• Единообразная работа, основанная на синтаксическом и семантическом интерфейсе. Работа с типами, которые подчиняются синтаксическому и семантическому интерфейсу, может выполняться единообразно. Интерфейсы в данном случае представляют синтаксическую сущность и не основаны на сигнатурах, так что допустима подстановка любого типа, который удовлетворяет данному синтаксису. Например, пусть дана инструкция >int i = p->f(5);. Если >p — указатель на класс >Base, эта инструкция вызывает определенную функцию интерфейса, вероятно, >virtual int f(int). Но если >p имеет обобщенный тип, то этот вызов может быть связан со множеством различных вещей, включая, например, вызов перегруженного оператора >operator->, который возвращает тип, в котором определена функция >X f(double), где >X — тип, который может быть преобразован в int.

• Статическая проверка типов. Все типы проверяются статически.

• Статическое связывание (мешает раздельной компиляции). Все типы связываются статически.

• Эффективность. Вычисления во время компиляции и статическое связывание позволяют достичь оптимизации и эффективности, недоступных при динамическом связывании.

Определите ваши приоритеты и используйте каждый вид полиморфизма там, где проявляются его сильные стороны.

Следует сочетать статический и динамический полиморфизм для того, чтобы получить преимущества обоих видов полиморфизма, а не для того, чтобы комбинировать их недостатки.

• Статика помогает динамике. Используйте статический полиморфизм для реализации динамически полиморфных интерфейсов. Например, у вас может быть абстрактный базовый класс >Command, и вы определяете различные реализации в виде шаблона

>template class ConcreteCommand: public Command

В качестве примеров можно привести реализации шаблонов проектирования >Command и >Visitor (см. [Alexandrescu01] и [Sutter04]).

• Динамика помогает статике. Обобщенный, удобный, статически связываемый интерфейс может использовать внутреннюю динамическую диспетчеризацию, что позволяет обеспечить одинаковую схему размещения объектов. Хорошими примерами могут служить реализации размеченных объединений (см. [Alexandrescu02b] и [Boost]) и параметр