简体   繁体   中英

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 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?

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).

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 eg 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, eg 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, eg std::string ), so the compiler-generated default copy constructor and destructor work just fine.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM