Harold Serrano

View Original

C++ tip 7: Be sure to copy all of an object's data members and its base class parts

Hi there,

In C++ there are two methods that are in charge of copying objects. They are called:

  • Copy constructor
  • Copy assignment operator

The following class has a copy constructor and a copy assignment operator:

class Polygon{
        public:
        //...
        //Copy constructor
        Polygon(const Polygon& p):name(p.name){}

        //Copy assignment operator
        Polygon& operator=(const Polygon& p){
            name=p.name;    //copy p's data
            return *this;
        }
        private:
            std::string name;
    };

This is nothing new to you. When we call the copy constructor or copy assignment, the data member name is copied onto the new object.

Now, let's say that you add another data member to the class called distance.

class Polygon{
        public:
        //...
        //Copy constructor
        Polygon(const Polygon& p):name(p.name){}

        //Copy assignment operator
        Polygon& operator=(const Polygon& p){
            name=p.name;    //copy p's data
            return *this;
        }
        private:
            std::string name;
            float distance;
    };

What do you think will happen if you forget to implement the copy of the new data member in both copy constructor and copy assignment?

Yep, you are right. The data member distance will not be copied. One of the tip from the book Efficient C++ is to make sure to copy all of an object's data members.

So an easy fix is as shown below:

class Polygon{
        public:
        //...
        //Copy constructor
        Polygon(const Polygon& p):name(p.name),distance(p.distance){}

        //Copy assignment operator
        Polygon& operator=(const Polygon& p){
            name=p.name;    //copy p's data
            distance=p.distance;
            return *this;
        }
        private:
            std::string name;
            float distance;
    };

This may seem obvious to you but the problem usually arises when you use derived classes. Let's see what happens when you have a derived class and implement a copy constructor and a copy assignment.

class Triangle:Polygon{
        public:
        //...
        //Copy constructor
        Triangle(const Triangle& t):coordinate(t.coordinate){}

        //Copy assignment operator
        Triangle& operator=(const Triangle& t){
            coordinate=t.coordinate;    //copy t's data
            return *this;
        }
        private:
            float coordinate
    };

When you do a copy of your derived class, the data members from the base class will not be copied!!! It is your duty to inform the copy methods to also copy the base class's copy constructor and assignment. This is done as follows:

class Triangle:Polygon{
        public:
        //...
        //In the copy constructor invoke the base class copy constructor
        Triangle(const Triangle& t):Polygon(t),coordinate(t.coordinate){}

        //Copy assignment operator
        Triangle& operator=(const Triangle& t){
            //inform the base class to copy its data members
            Polygon::operator=(t);
            coordinate=t.coordinate;    //copy t's data
            return *this;
        }
        private:
            float coordinate
    };

I hope this tip is helpful.

If you want to receive more tips, sign up to my newsletter below.