Foo f1;
Foo f2(f1);
Yes this will do what you expect it to:
The f2 copy constructor Foo::Foo(Foo const&) is called.
This copy constructs its base class and then each member (recursively)
If you define a class like this:
class X: public Y
{
private:
int m_a;
char* m_b;
Z m_c;
};
The following methods will be defined by your compiler.
- Constructor (default) (2 versions)
- Constructor (Copy)
- Destructor (default)
- Assignment operator
Constructor: Default:
There are actually two default constructors.
One is used for zero-initialization
while the other is used for value-initialization
. The used depends on whether you use ()
during initialization or not.
// Zero-Initialization compiler generated constructor
X::X()
:Y() // Calls the base constructor
// If this is compiler generated use
// the `Zero-Initialization version'
,m_a(0) // Default construction of basic PODS zeros them
,m_b(0) //
m_c() // Calls the default constructor of Z
// If this is compiler generated use
// the `Zero-Initialization version'
{
}
// Value-Initialization compiler generated constructor
X::X()
:Y() // Calls the base constructor
// If this is compiler generated use
// the `Value-Initialization version'
//,m_a() // Default construction of basic PODS does nothing
//,m_b() // The values are un-initialized.
m_c() // Calls the default constructor of Z
// If this is compiler generated use
// the `Value-Initialization version'
{
}
Notes: If the base class or any members do not have a valid visible default constructor then the default constructor can not be generated. This is not an error unless your code tries to use the default constructor (then only a compile time error).
Constructor (Copy)
X::X(X const& copy)
:Y(copy) // Calls the base copy constructor
,m_a(copy.m_a) // Calls each members copy constructor
,m_b(copy.m_b)
,m_c(copy.m_c)
{}
Notes: If the base class or any members do not have a valid visible copy constructor then the copy constructor can not be generated. This is not an error unless your code tries to use the copy constructor (then only a compile time error).
Assignment Operator
X& operator=(X const& copy)
{
Y::operator=(copy); // Calls the base assignment operator
m_a = copy.m_a; // Calls each members assignment operator
m_b = copy.m_b;
m_c = copy.m_c;
return *this;
}
Notes: If the base class or any members do not have a valid viable assignment operator then the assignment operator can not be generated. This is not an error unless your code tries to use the assignment operator (then only a compile time error).
Destructor
X::~X()
{
// First runs the destructor code
}
// This is psudo code.
// But the equiv of this code happens in every destructor
m_c.~Z(); // Calls the destructor for each member
// m_b // PODs and pointers destructors do nothing
// m_a
~Y(); // Call the base class destructor
- If any constructor (including copy) is declared then the default constructor is not implemented by the compiler.
- If the copy constructor is declared then the compiler will not generate one.
- If the assignment operator is declared then the compiler will not generate one.
- If a destructor is declared the compiler will not generate one.
Looking at your code the following copy constructors are generated:
Foo::Foo(Foo const& copy)
:bar(copy.bar)
{}
Bar::Bar(Bar const& copy)
:i(copy.i)
,baz(copy.baz)
{}
Baz::Baz(Baz const& copy)
:j(copy.j)
{}
m_a
,m_b
, andm_c
aren't very informative names. This wouldn't be a problem, except that you initially define them asm_a
,m_c
(for thechar *
), andm_d
(for theZ
type). I suspect that more informative names would have avoided this minor error. +1 anyway for a good post. – Litchfield