Я думаю, что Бьярне означает, что obj
или, точнее, объект, на который он указывает, не может быть легко основан на стеке в этом коде:
int f(int arg)
{
std::unique_ptr<Base> obj;
switch (arg)
{
case 1: obj = std::make_unique<Derived1 >(); break;
case 2: obj = std::make_unique<Derived2 >(); break;
default: obj = std::make_unique<DerivedDefault>(); break;
}
return obj->GetValue();
}
Вы не можете иметь в стеке объект, который меняет свой класс или изначально не уверен, к какому именно классу он принадлежит.
(Конечно, чтобы быть по-настоящему педантичным, можно разместить объект в стеке с помощью размещения нового в выделенном alloca
пространстве. Тот факт, что существуют сложные обходные пути, не относится к этому вопросу, хотя.)
Следующий код также не работает должным образом:
int f(int arg)
{
Base obj = DerivedFactory(arg); // copy (return by value)
return obj.GetValue();
}
Этот код содержит ошибка среза объекта ошибка: пространство стека для obj
настолько же велико, как экземпляр класса Base
; когда DerivedFactory
возвращает объект производного класса, который имеет несколько дополнительных членов, они не будут скопированы в obj
, что делает obj
недействительным и непригодным для использования в качестве производного объекта (и, возможно, даже непригодным для использования в качестве базового объекта.)
Подводя итог, можно сказать, что существует класс полиморфного поведения, который не может быть достигнут с помощью стековых объектов каким-либо простым способом.
Конечно, любой полностью построенный производный объект, где бы он ни хранился, может действовать как базовый объект и, следовательно, действовать полиморфно. Это просто следует из отношения is-a , которое объекты наследуемых классов имеют с базовым классом.