【问题标题】:How can I implement "operator=" and "copy c'tor" correctly in this case?在这种情况下,如何正确实现“operator=”和“copy c'tor”?
【发布时间】:2018-07-09 07:10:37
【问题描述】:

鉴于BaseClassSomeClass 类(实现operator=copy c'tor),我编写了以下类:

class DerivedClass : public BaseClass {
 SomeClass* a1;
 SomeClass* a2;
public:
 // constructors go here …
 ~DerivedClass() { delete a1; delete a2;}
 // other functions go here ...
};

我的问题是:我怎样才能实现DerivedClass 类的operator=?我怎样才能实现这个类的copy c'tor

我想通过以下方式实现operator=

DerivedClass& operator=(const DerivedClass& d)  {
if (this==&d) return *this;
SomeClass* tmp1 = new SomeClass (*(d.a1));
SomeClass* tmp2 = NULL;
try {
tmp2 = new SomeClass(*(d.a2));
} catch (const std::exception& e) {
delete tmp1;
throw e;
}
delete this->a1;
delete this->a2;
this->a1 = tmp1;
this->a2 = tmp2;
return *this;
}  

但是我不确定解决方案,特别是BaseClass的字段呢?

另外,如何实现DerivedClasscopy c'tor?我可以用operator= 做吗?

【问题讨论】:

    标签: class c++11 operator-overloading copy-constructor derived-class


    【解决方案1】:

    我的建议是您不要实现它们,而是选择the rule of zero。这可以很容易地实现,例如std::shared_ptr(如果可以接受a1a2 的共享所有权)。

    但如果您必须实现自己的复制构造函数和复制赋值运算符,那么您首先需要调用父类构造函数或运算符,然后再进行自己的复制。

    对于构造函数,你使用constructor-initializer列表:

    DerivedClass(DerivedClass const& other)
        : BaseClass(other), a1(new SomeClass(*other.a1)), a2(new SomeClass(*other.a2))
    {}
    

    a1(new SomeClass(*other.a1) 部分使用其复制构造函数创建一个新的SomeClass 对象,并初始化您的成员a1 以指向新对象。

    最后一部分也应该是对复制赋值运算符的提示,因为它也可以在那里使用:

    DerivedClass& operator=(DerivedClass const& other)
    {
        if (this != &other)
        {
            // First let the parent copy itself
            BaseClass::operator=(other);
    
            // Deep copy of the members
            delete a1;
            a1 = new SomeClass(*other.a1);
    
            delete a2;
            a2 = new SomeClass(*other.a2);
        }
    
        return *this;
    }
    

    【讨论】:

    • 但是如果出现异常,它不会保留this 的值,不是吗?也就是说,如果当我们做 a2 = new SomeClass(*(other.a2)); 时,我们会得到 std::bad_alloc ,所以我们会想要像开头一样保留 this 的字段,不是吗?
    • 此外,是否存在通过operator= 实现copy constructor 的方法?
    • @Software_t 几乎所有异常都是不可恢复的。如果您没有足够的内存来分配对象,那么继续的意义何在?好的,在某些情况下您可以释放内存,但必须重新创建对象,赋值也是如此,而且您必须在比复制构造函数和赋值运算符更高的级别上执行此操作。
    • 好吧,仅供理解,如果我愿意,我可以在a1a2更新后做BaseClass::operator=(other);吗?或者它必须是在开始?
    • @Software_t 可以是任意顺序。
    猜你喜欢
    • 2021-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-10
    • 2020-08-06
    • 2012-06-06
    • 2022-01-11
    • 1970-01-01
    相关资源
    最近更新 更多