以下案例指出了切片问题: 在分配期间: https ://stackoverflow.com/a/274634/640639
在函数调用期间: 什么是对象切片?
我的问题是,如果将赋值运算符和复制构造函数声明为虚拟并且派生类适当地复制所需的数据,这两种情况都不会得到解决吗?如果原则上是这样,在这些情况下传递值应该仍然有效,对吗?
以下案例指出了切片问题: 在分配期间: https ://stackoverflow.com/a/274634/640639
在函数调用期间: 什么是对象切片?
我的问题是,如果将赋值运算符和复制构造函数声明为虚拟并且派生类适当地复制所需的数据,这两种情况都不会得到解决吗?如果原则上是这样,在这些情况下传递值应该仍然有效,对吗?
不会。参数是按值传递的,因此会创建一个新的基础对象。
没有虚拟构造函数,virtual
意思是“依赖于动态类型this
”,在构造函数运行之前,对象甚至都不存在,所以它不能有派生的动态类型。
虚拟赋值运算符也无济于事,因为它们取决于被分配对象的类型,而不是被分配对象的类型。
如果您希望能够按值复制但仍然具有多态行为,则可以创建一个对象,该对象包含指向另一个对象的指针,并在其构造函数和赋值运算符中克隆该对象(使用类似Martinho Fernandes' Wheels中的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...
显然,您不能将复制构造声明为virtual
:尚无对象。不过,您可以禁用复制构造。
也就是说,赋值virtual
仍然不起作用,因为在切片对象时,所分配对象的静态类型仍然只是一个基类。它永远不会成为独立于您分配给它的类型的派生类。