www.easyCPlusPlus.com

Easy C++

www.easyCPlusPlus.com

C++ Tutorial - Lesson 20: Copy Constructors

Copy Constructors, continued

by John Kopp

Support this site at no cost to you

Now suppose that "John" is promoted.

int main()
{
    Employee programmer("John",22);
    cout << programmer.getName() << endl;

    //Lots of code ....

    Employee manager(&programmer);
        //Creates a new Employee "manager",
        //which is an exact copy of the
        //Employee "programmer".

    return 0;
}

The above program contains a serious bug and will die with an exception when run. The problem is that the default member-wise copy constructor is being used to create the "manager" object. This provides correct behavior for members held by value, such as _id. We want the ID number copied from "programmer" to "manager". But the member-wise copy copies the address stored in the pointer _name in "programmer" to the pointer _name in "manager". We now have two pointers both containing the same address, that is, both referring to the same block of memory in the free store. Suppose that a new individual is hired as "programmer". When the name is updated, it will not only change the name of the programmer, but also the manager! Remember, there is only a single block in the free store and both objects hold pointers to it. This is surely not what we want. Additionally, when the first of these objects goes out of scope its destructor will be called. The block of memory in the free store will be released. When the second object tries to reference this memory, bad things happen. For instance, when I run the above program, programmer's destructor gets called first. It works fine and frees the block in memory. When manager's destructor is called, an exception is thrown when the delete is attempted because that block of memory has already been released.

The solution to this problem is to define our own copy constructor. When a new object is created using this constructor, we need to be sure to allocate a new block of memory in the free store and to copy the name itself rather than the pointer to name. By convention, the object passed into copy constructors is called "rhs", for right hand side. Here is the Employee class with a copy constructor defined.

class Employee {
public:
    Employee(char *name, int id);
    Employee(Employee &rhs);
    ~Employee();
    char *getName(){return _name;}
    int getId() {return _id;}
    //Other Accessor methods
private:
    int _id;
    char *_name;
};

Employee::Employee(char *name, int id)
{
    _id = id;

    _name = new char[strlen(name) + 1];
            //Allocates an character array object
    strcpy(_name, name);
}

Employee::~Employee() {
    delete[] _name;
}

Employee::Employee(Employee &rhs)
{
    _id = rhs.getId();
    _name = new char[strlen(rhs.getName()) + 1];
    strcpy(_name,rhs._name);
}

As a concluding note, the reference passed into the copy constructor should be declared const. We'll see more on this in a later lesson.

Previous Page       Next Page