Re: virtual function being private in derived class
* Robert Fendt -> Sam:
Apart from that, (and I know it does not correspond to your
original question, but you *did* say you are currently learning
C++), you should consider limiting your use of public virtuals
in C++ anyway. However, I will not say (like others do
sometimes) "do not use them at all".
They have their uses, and there's nothing wrong with them if you
use them e.g. to define an abstract interface without inheriting
further from the implementing classes. However, there are
problems that newcomers to C++ often do not expect, especially
if they come from a Java or C# background. The two main sources
of problems are (in my experience):
(1) There is (currently) no 'override' annotation. C++ 0x *will*
have it, but it will probably still take several years before
usable implementations actually become available. In current
standard C++, you can inadvertently create a new function
instead of overriding the base definition without realising it.
This is a test case for a macro CPPX_IS_OVERRIDE_OF:
<code>
class Base
{
protected:
virtual void foo( int, char const* ) const = 0;
};
class Derived:
public Base
{
protected:
virtual void foo( int a, char const* b ) const
{
CPPX_IS_OVERRIDE_OF( Base::foo,(a, b) ); // Fine.
}
virtual void bar() const
{
#if defined( CERR_NONEXISTING )
CPPX_IS_OVERRIDE_OF( Base::bar,() ); // Compilation error.
#endif
}
};
</code>
The macro does not guarantee to detect that you're not overriding. It's just a
code documentation tool, documenting your intention, with a *best effort*
checking that in most cases will detect any problem. It's defined like this
(modulo namespaces and header file packaging, I removed that for this posting):
<code>
template< typename T >
inline void suppressUnusedWarning( T const& ) {}
// The following macro is comment-like, but performs such checking as it can.
#define CPPX_IS_OVERRIDE_OF( memberSpec, args ) \
suppressUnusedWarning( sizeof( (memberSpec args, 0) ) )
</code>
Use of a macro like this is one argument in favor of generally not making
virtuals 'private', but rather make them 'protected', at least by default.
Until I wrote that macro, some years ago, I strongly disagreed with the FAQ's
recommendation of 'protected'; now I hail Marshall Cline for his foresight! :-)
(2) Virtual functions and function overloading are a dangerous
mixture in C++. Consider two virtual functions which differ
only by their signatures: now overriding just one in a derived
class actually hides the other if you do not explicitly
instruct the compiler to do otherwise. This is especially
irksome in conjunction with (1).
To help at least with point (2), the "non-virtual interface
pattern" has gained some popularity. In the interface class, the
public (possibly overloaded) functions are declared and defined
as non-virtual functions which in turn call non-overloaded,
private, purely virtual functions. This separates overloading and
inheritance, with overload resolution always happening in the
base class. The pattern also allows for selective overriding of
functionality and apart from that provides a central entry point
for debugging purposes via the base.
Thank you. I never thought of it this way. It's very clarifying. Another reason
is checking of preconditions and postconditions. If only C++ had DBC support...
Cheers,
- Alf