C++ FAQ - How to write copy ctors/operators
Today I got really confused by explicit vs. implicit base copy ctor calls.
Although it makes sense with hindsight, I haven't found it on
http://www.parashift.com/c++-faq-lite and think this should really be
part of either
[19] Inheritance ? basics
or of
[10] Constructors
The problem I had was that I wasn't aware how to correctly write a copy
ctor (and operator) in the face of inheritance: The problem is, that the
copy ctor provided by the compiler will implicitly call the *copy* ctor
of the base class. However, if I supply my own copy ctor I am required
to also explicitly call the copy ctor of the base class as otherwise the
*default* ctor will be called.
I think this is easily overlooked (as was by me) and really should be
part of the FAQ.
Find some sample code below.
cheers,
Martin
-- test.cpp --
#include <iostream>
// A simple struct that provides some logging for demonstration purposes
struct Simple {
int x;
Simple()
: x(0)
{
std::cout << "Simple()\n";
}
Simple(Simple const& o)
: x(o.x)
{
std::cout << "Simple(Simple const& o)\n";
}
Simple& operator=(Simple const& o)
{
x = o.x;
std::cout << "Simple& operator=(Simple const& o)\n";
return *this;
}
};
// Trying to inherit from Simple
// The copy ctor/operator is bugged
struct Wrong : public Simple {
int cannot_copy;
Wrong()
: cannot_copy(0)
{ std::cout << " Wrong()\n"; }
Wrong(Wrong const&)
: cannot_copy(0)
{ std::cout << " Wrong(Wrong const& o)\n"; }
Wrong& operator=(Wrong const&)
{
std::cout << " Wrong& operator=(Wrong const& o)\n";
// cannot_copy ... keep
return *this;
}
};
// Correctly implementing the copy ctor/operator
// Have to explicitly call the base members!
struct Correct : public Simple {
int cannot_copy;
Correct()
: cannot_copy(0)
{ std::cout << " Correct()\n"; }
Correct(Correct const& o)
: Simple(o) // don't forget to explicitly call the base copy ctor!
, cannot_copy(0)
{ std::cout << " Correct(Correct const& o)\n"; }
Correct& operator=(Correct const& o)
{
std::cout << " Correct& operator=(Correct const& o)\n";
Simple::operator=(o); // don't forget to explicitly copy the base
object!
// cannot_copy ... keep
return *this;
}
};
int main(int, char**)
{
using namespace std;
Simple s1;
Wrong w1;
Correct c1;
s1.x = 99;
w1.x = 666;
c1.x = 777;
cout << "Copy construct and copy Correct object ...\n";
Correct c2(c1);
cout << "c2.x: " << c2.x << "\n";
c2 = c1;
cout << "c2.x: " << c2.x << "\n";
cout << "Copy construct and copy Wrong object ...\n";
Wrong w2(w1);
cout << "w2.x: " << w2.x << "\n";
w2 = w1;
cout << "w2.x: " << w2.x << "\n";
}
-- test output --
Simple()
Simple()
Wrong()
Simple()
Correct()
Copy construct and copy Correct object ...
Simple(Simple const& o)
Correct(Correct const& o)
c2.x: 777
Correct& operator=(Correct const& o)
Simple& operator=(Simple const& o)
c2.x: 777
Copy construct and copy Wrong object ...
Simple()
Wrong(Wrong const& o)
w2.x: 0
Wrong& operator=(Wrong const& o)
w2.x: 0
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]