Reputation: 41
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
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
andstruct
), 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
Reputation: 29017
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