Следующие случаи указывают на проблему срезов:
Во время выполнения задания:
https://stackoverflow.com/a/274634/640639
Во время вызова функции:
Что такое нарезка объектов?
Мой вопрос: не решены ли оба этих случая, если оператор присваивания и конструктор копирования объявлены виртуальными, а производный класс соответствующим образом скопирует необходимые данные? Если это так, то в принципе передача по значению все еще должна работать в этих случаях, верно?
Очевидно, вы не можете объявить конструкцию копии virtual
: Объекта пока нет. Вы можете отключить конструкцию копирования, хотя.
Тем не менее, делая назначение virtual
все еще не работает, потому что при нарезке объектов статический тип назначенного объекта все еще является просто базовым классом. Он никогда не станет производным классом, независимо от того, какой тип вы ему назначаете.
Нет. Аргумент передается по значению, и поэтому создается новый базовый объект.
Виртуального конструктора не существует, так как virtual
означает «зависит от динамического типа this
«, и до запуска конструктора объект даже не существует, поэтому он не может иметь производный динамический тип.
Виртуальные операторы присваивания также не помогут, так как они будут зависеть от типа объекта, которому присваиваются, а не от типа объекта, которому присваиваются.
Если вы хотите иметь возможность копировать по значению, но при этом иметь полиморфное поведение, вы можете создать объект, который содержит указатель на другой объект и который клонирует объект в его конструкторах и операторах присваивания (используя что-то вроде value_ptr из библиотеки Колес Мартиньо Фернандеса):
class Base {
public:
virtual Base* clone() const = 0;
virtual void do_stuff() = 0;
};
class CopyablePolymorphic {
public:
CopyablePolymorphic(Base* base) : ptr(base) {}
private:
value_ptr<Base> ptr;
};
class Derived1 : public Base {
public:
virtual Base* clone() const {
return new Derived1(*this);
}
virtual void do_stuff() {
//Derived1 stuff
}
};
class Derived2 : public Base {
public:
virtual Base* clone() const {
return new Derived2(*this);
}
virtual void do_stuff() {
//Derived2 stuff
}
};
//etc...