Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assigning base class members in copy assignment operator

I've got a class that inherits from a MSFT class, and therefore cannot be changed, and I'd like my derived class to have identical behavior for its copy constructor and copy assignment operator. The trouble I'm having is that in the copy constructor, you are free to invoke a constructor for the base class in the initializer list, but in the operator, this is not an option. How can I properly recreate this behavior in the assignment operator? Is it sufficient to just call the base class's constructor in the body of the operator overload?

Additional note: the base class inherits from CObject, which has operator=() and the copy constructor as private and unimplemented methods, so unfortunately any calls to those will result in a compile error.

I've provided a simplified code scenario below:

Class declarations:

class Base    
{
protected:
    int baseInt;
public:
    Base(int);
}

class Derived : public Base
{
public:
    Derived(const Derived& other);
    Derived& operator=(const Derived& rhs);
private:
    int derivedInt;
}

Derived class member functions:

// Copy Constructor
Derived(const Derived& other) : Base(5)
{
    derivedInt = other.derivedInt;
}

// Copy Assignment Operator
Derived& operator=(const Derived& rhs)
{
    if (&rhs != this)
    {
        derivedInt = other.derivedInt;
        return *this;
    }
}

EDIT: Updated syntax and added CObject note

like image 984
CJ McAllister Avatar asked Dec 21 '22 07:12

CJ McAllister


2 Answers

In the general case, you do that either by explicitly calling operator= for the base class subobject, or by using the copy&swap idiom, if available:

//explicit call to base operator=
Derived& operator=(const Derived& rhs)
{
  Base::operator=(rhs); //
  derivedInt = rhs.derivedInt;
  return *this;
}


//or copy&swap:
Derived& operator=(const Derived& rhs)
{
  Derived tmp(rhs); //copy
  tmp.swap(*this);
  return *this;
}

void swap(Derived& other)   
{
  Base::swap(other);
  std::swap(derivedInt,other.derivedInt);
}

Update: since your base class is not meant to be copy-assigned, your derived class should not be copy-assigned either. There are some cases where classes contain noncopyable parts but are perfectly copyable. In those cases the noncopyable part is something that does not directly contribute to the class objects' state, e.g. a unique ID. Then those parts will normally not be changed during assignment. However, in those cases the noncopyable parts should not be contained by inheritance but rather by aggregation.

Shortly said: Iheritance means "is-A" relationship. Your Base cannot be copied. Your Derived is a Base. Thus your Derived cannot be copied either.

like image 182
Arne Mertz Avatar answered Dec 24 '22 01:12

Arne Mertz


Like this

Derived& operator=(const Derived& rhs)
{
    Base::operator=(rhs);
    derivedInt = rhs.derivedInt;
    return *this;
}
like image 34
john Avatar answered Dec 24 '22 03:12

john