To extend a class in C++, distinguish two cases.
If the new function can be expressed in terms of the current interface, use non-member functions
// B.hpp
void print2(A const& a)
{
// pre-call extensions (logging, checking etc.)
a.print1();
// post-call extensions (logging, checking etc.)
}
If the new function requires knowledge about the current implementation, use class inheritance
// B.hpp
// WARNING: here be dragons, read on before using this in production code
class B: public A
{
public:
void print2() const // compiler-generated signature: void print2(B const*)
{
// pre-call extensions (logging, checking etc.)
print1();
// post-call extensions (logging, checking etc.)
}
};
However, deriving from a class that was not intended to be a base class, can be dangerous. In particular, if A
does not have a virtual
destructor, you can get into trouble if you ever use pointers to dynamically allocated B
objects in places where they would be deallocated as if they were pointers to A
objects.
Furthermore, because A::print1()
was not made virtual
, you get into all sorts of name hiding problems, which is why you have to name the extended function B::print2()
.
Long story short: know which kind of classes you are writing. If you want to extend the behavior based on a class implementation, then you better make it suitable as a base class (virtual destructor, virtual functions that you can override). Otherwise, mark your class as final
(new C++11 contextual keyword). This will generate compiler warnings if you try to override existing functions.
NOTE: In other languages (notably D), it is possible to let the compiler automatically find non-member functions print2(a)
when it sees the syntax a.print2()
. Unfortunately, such uniform function call syntax is not on the roadmap yet for C++.