C ++ имеет два различных механизма для написания фрагмента кода, который ведет себя по-разному в зависимости от типов объектов, на которые действуют:
virtual
функций и наследования, которые работают на * 1005Шаблонные функции * runtime и - , работающие в время компиляции .
Ваш пример с параметрами auto
(которые, по-видимому, на самом деле не были приняты в C ++ 14 за исключением лямбда-функций ) работает с шаблонами.Код, который вы написали, эквивалентен
template <typename T>
void print(T& shape) {
cout << shape.name();
}
Этот код предполагает, что тип T
может быть определен во время компиляции , так как компилятор должен знать типT
для заполнения шаблона.Как только компилятор узнает об этом, он может сказать: «Ах, я знаю, что это за тип! Я сгенерирую код для непосредственного вызова функции name
этого типа, и я точно знаю, какую функцию он будет вызывать».
С другой стороны, виртуальные функции и наследование работают при времени выполнения .Например, предположим, что вы хотите написать функцию, которая считывает некоторые данные из сети, а затем возвращает Circle
или Rectangle
.У вас может быть такой код:
Shape* myShape = decodeNetworkData();
Здесь все, что знает компилятор, это то, что myShape
указывает на что-то вроде Shape
, но он не может определить, является ли это круг или квадрат,Поэтому, если бы вы позвонили
cout << myShape->name();
, то компилятор сказал бы: «Я знаю, что вы вызываете какую-то версию name
, но я не знаю, какую. Но это нормально! Я»Я сгенерирую некоторый код, который смотрит на динамический тип myShape
(тип того, на что он фактически указывает) и использует его для поиска, какую функцию вызывать. "
Обратите внимание, что код компилятор будетГенерирование в каждом случае отличается и поведение будет отличаться.В первом случае компилятор точно знает, какую функцию вызывать.Во-вторых, компилятор не знает, какую функцию вызывать, и должен сгенерировать дополнительный код, чтобы все заработало.Но, с другой стороны, если у вас не было типа Shape
с виртуальной функцией name
, вы могли бы заставить фрагмент кода «декодировать байты сети» работать с вашей первой функцией, так как компиляторЯ должен заранее знать, какой тип он будет видеть, приходя по сети.
Было предложено пометить этот вопрос как , дубликат этого старого вопроса о шаблонах и наследовании хотя внешне это не тот же вопрос.Как только вы узнаете, что ключевое слово auto
в этом контексте означает «это действительно шаблонная функция», вы можете просмотреть другой предложенный вопрос, чтобы получить дополнительные примеры различий между статическим полиморфизмом (с помощью шаблонов).) и полиморфизм времени выполнения (с виртуальными функциями).