Шаблонный ввод утки C++ по сравнению с чистым виртуальным наследованием базового класса

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

// 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();
}
12
задан Giovanni Funchal 23 July 2010 в 16:20
поделиться

4 ответа

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

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

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

11
ответ дан 2 December 2019 в 21:22
поделиться

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

2
ответ дан 2 December 2019 в 21:22
поделиться

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

2
ответ дан 2 December 2019 в 21:22
поделиться

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

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

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

0
ответ дан 2 December 2019 в 21:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: