我有一堂课Base
class Base{
public:
virtual ~Base();
//I'm not sure about this, should it be virtual, or should it be "pure" virtual?
virtual Base& operator=(const Base&);
}
如果Base
类是由几个类派生的,例如
class Derived1: public Base{
//...data
//standard assignment operator, it works for objects of class Derived1
Derived1& operator=(const Derived&){
//perform deep copy here
std::cout<<"Derived1 assignment operator"<<std::endl;
}
}
每个类都必须具有赋值运算符,因为这些类的某些数据成员是指针,因此我必须对它们进行深层复制。然后将以下代码不工作:
Base *d1 = new Derived1();
Base *d1_another = new Derived1();
//assignment operator is not called.
*d1 = *d1_another
如果我将基址的赋值运算符设为纯虚拟virtual Base& operator=(const Base&) = 0
,则必须在每个子类中实现它。
class Derived1: public Base{
//...data
//implementation of the base's assignment operator
Base& operator=(const Base&){
//how to access Derived1 fields? Casting?
}
}
但是,如果传递给赋值运算符的对象是Base
,该如何复制子类的成员?
PS我知道这不是一个很好的设计,但是,如果假设我有一个指向基数std::vector<Base*> v
的对象的指针向量,并且其中充满了派生类的对象,那我应该怎么做? (Derived1
,Derived2
,还有其他一些类),有时我不得不将一个对象复制到另一个对象中。我不明白什么是另一种解决方案。
答案 0 :(得分:1)
请注意,赋值运算符的参数不是Base
的 object ,而是对Base
的 reference 。这意味着您可以使用dynamic_cast
向下投射到对Derived1
对象的引用。
您还可以使用the Curiously Recurring Template Pattern (or CRTP)在Base
类中声明赋值运算符,并使用正确的参数类型并返回。
答案 1 :(得分:0)
我不会用operator=
做这种事情。如何处理将Derived2
分配给Derived1
?
相反,我会有一个assign
表示成功或失败,例如
class Base{
protected:
Base& operator=(const Base&) = default;
Base& operator=(Base&&) = default;
public:
virtual ~Base() = default;
virtual bool assign(const Base&) = 0;
/* maybe ? virtual bool assign(Base&&) = 0; */
}
class Derived1: public Base{
//...data
protected:
Derived1& operator=(const Derived1 &) = default;
public:
bool assign(const Base & base){
if (const Derived1 * derived = dynamic_cast<const Derived1 *>(&base))
{
*this = *derived;
return true;
}
return false;
}
}
int main() {
Base *d1 = new Derived1();
Base *d1_another = new Derived1();
Base *d2 = new Derived2();
//assignment operator is not called.
assert(d1->assign(*d1_another)); // expect true, d1 is changed
assert(!d2->assign(*d1_another)); // expect false, d2 is unchanged
}