I have this simplified code example:
class Base {
Base() = default;
Base(const Base& src) {
// construct by copying src etc. - ok, legal even if src points to Derived object
}
Base(Base&& src) {
// construct by moving src - stealing its resources, ok, it was invented for this,
// but.. what if src points to Derived object?
}
};
class Derived : public Base {
};
void foo() {
Derived derived;
Base base_by_copy_constructor(derived); // legal, derived cannot be touched so nothing will be wrong
Base base_by_move(std::move(derived)); // uu? what's gonna happen, part of derived object (Base class) was moved..
}
Is such a behaviour proper? That can lead to weird problems because Base part od Derived object was actually 'deinitialized'. So.. Should we avoid deriving from class which has move operator, or make our Derived class resistant to 'moving' its base part?
(Of course - this is only example, classes have no data, move operator does not do anything, so here nothing will go wrong. I'm asking about a real world example of such a.. situation :) )
Their is no problem with slicing, this can be done explictly and intensionnaly.
Nevertheless when dooing OO programming in general, there is only one rule de follow: Do not let the possibility to any entity which is external to your object(or component) have the opportunity to break invariants.
So if invoking a member or a constructor of the base class could break an invariant that your derived class establish between it and its base, so the base must be private. (You can still bring public the members of the base that do not break invariants with using base::member
)