Daniel
Daniel

Reputation: 41

Is it necessary to create a Copy Constructor for derived classes?

If I have a base class with a complex data member, let's say char*, and at the end of my inheritance chain I have another class with the same kind of DM, do I have to implement the CCTORs (Copy Constructors) of all the other classes on the way?

For example:

Animal Class:

class Animal
{
    int age;
    char* name;
    Animal() { ... } 
    Animal(const Animal &animal) { ..deep copying name..}
}

Mammal Class:

class Mammal : public Animal
{
    int height;
    Mammal() { ... } 
}

Horse Class:

class Horse : public Mammal 
{
    char* color;
    Horse() { ... } 
    Horse(const Horse &horse ) { ..deep copying color..}
}

Do I need to implement a CCTOR in Mammal, even though it has only an int as a data member?

Basically my question is: When copying a complex object (built from several classes), does the compiler activate the CCTOR of each part separately?

Edit: To be clear, I want to copy a Horse object. If I write my code as above, will its name be deep copied as well?

Upvotes: 3

Views: 2003

Answers (3)

melpomene
melpomene

Reputation: 85897

Do i need to implement a CCTOR in Mammal, even though it has only an int as a data member?

No.

when copying a complex object (built from several classes), does the compiler activate the CCTOR of each part separately?

Yes.

See e.g. https://en.cppreference.com/w/cpp/language/copy_constructor#Implicitly-defined_copy_constructor:

For non-union class types (class and struct), the constructor performs full member-wise copy of the object's bases and non-static members, in their initialization order, using direct initialization.

(Emphasis mine.)

It's like the base object is just another member of the class. If Animal works like a proper value type (has a copy constructor, assignment operator, and destructor that do the right thing), you don't have to do anything special in derived classes like Mammal.


Note, however, that modern C++ style strives to keep member management out of constructors. That is, e.g. Horse shouldn't be concerned with allocating (and deallocating) memory for color in its constructors (and destructor).

Instead every member should manage itself (you'll have to change the type of color to something else, e.g. std::string), so the compiler-generated default copy constructor and destructor work just fine.

Upvotes: 3

πάντα ῥεῖ
πάντα ῥεῖ

Reputation: 1

The problematic class members you have are the char* raw pointers.

In idiomatic c++ you can solve that problem using std::string instead, thus you don't need to specify any constructors:

class Animal
{
    int age;
    std::string name;
    Animal() = default; // not really neccessary, just for demonstration
                        // purpose
    Animal(const Animal &animal) = default; // not really neccessary, just for
                                            // demonstration purpose
};

class Mammal : public Animal
{
    int height;
};

class Horse : public Mammal 
{
    std::string color;
};

Upvotes: 0

No you don't. By default (like Mammal), the copy constructor will invoke the copy constructor of each base class (in order), and then the copy constructor of each member variable (in order). Thus the copy constructor for Mammal is fine.

Note my point about "copy constructor of each member variable". Of course the copy constructor of char* does nothing - but if you wrap char* inside a class with a suitable copy constructor, then Animal and Horse can both use that class for their member variable - and won't need their own copy constructor.

In fact of course, std::string is already provided for you (but I assume you have a more complex case in reality).

Upvotes: 4

Related Questions