Переменная типа A может содержать значение типа B (для некоторых определений «hold», как объясняют другие ответы), но определенно не наоборот. Чтобы вывести стандартный пример:
class Animal {};
class Dog : public Animal {};
class Cat : public Animal {};
Это законно, потому что Cat
происходит от Animal
:
Cat c;
Animal& a = c;
Это не так:
Animal a;
Cat& c = a;
Это безопасно для типов, потому что вы определили это так; весь смысл наследования состоит в том, чтобы позволить этому случиться, поэтому вы можете продолжать вызывать методы для общей переменной Animal
, не зная, какой базовый класс хранится в ней. Что касается вопроса производительности, то вызов виртуальных методов происходит медленнее, потому что решение о том, какой метод будет фактически вызываться (например, Cat::foo()
против Dog::foo()
, в зависимости от конкретного типа Animal
, хранящегося в переменной), должно выполняться при запуске -time - это называется динамическая отправка . С не виртуальными методами решение может произойти во время компиляции