Reputation: 29683
I have base class with custom copy constructor that takes care of alocated memory. I also have class dervied from that base. That derived class is not doing anything more with memory.
How should copy constructor look in dervied class? How about overwriting swap, move and assign?
Upvotes: 1
Views: 1466
Reputation: 39141
There's the so-called rule-of-five (formerly rule-of-three), which says if you have user-defined any of those:
than you'll probably also want to user-define the other four.
On the other hand, there's the rule-of-zero: Instead of defining those five special member functions, you can use resource objects (RAII) that automatically take care of these things.
Whether such an object is a data member or a base class (subobject) of some class C
doesn't care: The implicitly declared & defined special member functions of C
provided by the compiler will invoke the special member function of this resource object, which will most probably be sufficient.
hint: A more precise answer could be given for a specific example
Upvotes: 1
Reputation: 279325
You shouldn't have to do anything other than maybe for swap
. A base class is like a data member in this respect, the compiler-generated copy constructor and assignment (and moves if applicable) include it.
swap
is different because there's no compiler-generated swap
, just the default implementation in namespace std
and then whatever specialization or ADL-overload the programmer defines for a user-defined type.
So if there's already a function that looks like:
namespace foo {
void swap(Base &lhs, Base &rhs) {
lhs.swap(rhs); // or maybe the gory details are in this function
}
}
and you do nothing, and some user calls it like:
foo::swap(derived1, derived2);
then the base parts will be swapped and the derived parts won't, which is pretty bad.
Users shouldn't call swap like that, but you know what users are like. It might look especially tempting to the user if Base
and Derived
are in the same namespace, and they just assume it'll all work. So you might want to ensure that there's an overload for Derived
in order to stop them, if you think your users are (or your own code base is) unprincipled in how it calls swap
.
Users should call swap
like:
using std::swap;
swap(base1, base2);
swap(derived1, derived2);
That will call foo::swap
when used with Base
and std::swap
when called with Derived
. std::swap<Derived>
might be inefficient (if Base
has a swap implemented for efficiency, then Derived
should too). So you probably want to implement a swap
for Derived
for that reason too, but slow isn't as bad as wrong.
That said, you're asking about moves. If Derived
is efficiently movable then std::swap<Derived>
isn't bad. Maybe it can be improved on, maybe not, but it should be marginal because three moves is hard to beat.
You and users should also be aware that swap
does not play nicely with polymorphism (because in general two objects must have the same complete type in order for swapping them to make sense), and implementing it for a base class might cause trouble.
Derived d1, d2;
Base &b1 = &d1, &b2 = d2;
swap(b1, d2); // swaps just the base part
swap(b1, b2); // swaps just the base part
So firstly, users need to know not to call swap like that. Secondly, you might want to consider whether or not a Base
with a swap
is really well-designed as a base class.
Upvotes: 3
Reputation: 120031
You cannot "overwrite" a constructor. It's not a term in the C++ vocabulary. You can override a function, but only if it's virtual.
Normally you shouldn't do anything special in the constructors of children of any correctly written base class. Let each generation take care of itself.
Upvotes: 0