Search code examples
classc++11operator-overloadingcopy-constructorderived-class

How can I implement "operator=" and "copy c'tor" correctly in this case?


Given the classes BaseClass and SomeClass (that implements operator= and copy c'tor) , I writed the following class:

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

And my question is: How can I implements operator= of the class DerivedClass? And how can I implements copy c'tor of this class?

I thought to implements the operator= in the following way:

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;
}  

But I'm not sure about the solution, in particular, what about the fields of BaseClass?

In addition, how can I implement the copy c'tor of DerivedClass? Can I do it with operator=?


Solution

  • My suggestion is that you don't implement them, and instead go for the rule of zero. That can be easily accomplished with e.g. std::shared_ptr (if shared ownership of a1 and a2 is acceptable).

    But if you must implement your own copy-constructor and copy-assignment operators, then you first of all need to invoke the parent class constructor or operator, before you do your own copying.

    For the constructor, you use the constructor-initializer list:

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

    The part a1(new SomeClass(*other.a1) creates a new SomeClass object using its copy-constructor, and initializes your member a1 to point to the new object.

    And this last part should be a hint for you copy-assignment operator as well, as it can be used there too:

    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;
    }