Типизирование утилит в C ++ против наследования чисто виртуального базового класса - PullRequest
12 голосов
/ 23 июля 2010

Каковы рекомендации по выбору между типизацией шаблонов и наследованием чисто виртуального базового класса? Примеры:

// templates
class duck {
    void sing() { std::cout << "quack\n"; }
};

template<typename bird>
void somefunc(const bird& b) {
    b.sing();
}

// pure virtual base class
class bird {
    virtual void sing() = 0;
};

class duck : public bird {
    void sing() { std::cout << "quack\n"; }
}

void somefunc(const bird& b) {
    b.sing();
}

Ответы [ 5 ]

11 голосов
/ 23 июля 2010

С помощью шаблонной типизации вы делаете статический полиморфизм.Таким образом, вы не можете делать такие вещи, как

std::vector<bird*> birds;
birds.push_back(new duck());

Однако, поскольку вы полагаетесь на типизацию во время компиляции, вы немного более эффективны (ни один виртуальный вызов не предполагает никакой динамической отправки (основанной на динамическом типе)).

2 голосов
/ 23 июля 2010

Время компиляции против времени выполнения. Если вы хотите связать время компиляции, вам нужно использовать шаблоны. Если вы не знаете типы во время компиляции, вы должны использовать виртуальное наследование.

2 голосов
/ 23 июля 2010

Если с «шаблонной природой» широко распространяющихся вещей все в порядке, то шаблоны («типизированная утка во время компиляции») могут дать вам невероятную скорость (избегая «уровня косвенности», который неявен при вызове виртуальной функции) ) хотя, может быть, и с некоторыми затратами памяти (теоретически, хорошие реализации на C ++ могли бы избежать затрат памяти, связанных с шаблонами, но я не уверен, что такие высококачественные компиляторы обязательно будут доступны на все платформы, на которые нужно портировать ;-). Так что, по крайней мере, прагматично, это что-то вроде компромисса между скоростью и памятью. Если операции, которые вы выполняете, настолько медленны, как ввод-вывод, то, возможно, относительно небольшое увеличение скорости от отказа от виртуального вызова не очень важно для вашего варианта использования.

0 голосов
/ 28 ноября 2010

@ Джон прав. Если у вас есть два параметра ковариантного типа, у вас нет выбора, вы должны использовать шаблоны. Объектно-ориентированные методы обеспечивают диспетчеризацию во время выполнения, но она доступна только для типов, чьи методы имеют не более одного варианта аргумента (объект).

Наиболее интересные проблемы связаны с N-арными отношениями с N> 1, поэтому у вас обычно не остается иного выбора, кроме как использовать шаблоны. Пожалуйста, изучите стандартную библиотеку, чтобы увидеть, какая техника используется чаще всего.

0 голосов
/ 23 июля 2010

Это две совершенно разные вещи.Одно не является альтернативой другому.Функция шаблона обеспечивает общую операцию somefunc(), которая применяется ко всему классу типов, а не только к птицам.Тип его параметра должен быть известен во время компиляции.Виртуальный метод обеспечивает полиморфную операцию во время выполнения, специфичную для птиц.Точный тип параметра (this) не обязательно должен быть известен во время компиляции.

Поскольку они предоставляют различные функциональные возможности и не конфликтуют друг с другом, вам редко приходится выбирать междудва подхода.Решите, какой функционал вам нужен, и разумный подход будет очевиден.Это может быть даже комбинация двух.

(кстати, здесь неправильно используется термин «типизирование утки». Ни один из подходов не является типизацией утиной типики. Вы должны отбросить фразу из лексикона C ++.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...