Re: downcast to derived class in privately inherited base class te
"Ulrich Eckhardt" wrote:
Georg Krichel wrote:
template< typename D >
class Base
{
public:
virtual ~Base( ) { ; }
void doFunc( )
{
D* dp = &dynamic_cast< D& >( *this ); // CRASH at runtime!
// ... more code using "dp"
}
};
class Derived : private Base< Derived >
{
friend class Base< Derived >;
public:
void doFunc( ) { Base< Derived >::doFunc( ); }
};
If Base<Derived> is inherited "public", it just works, if inherited
"protected", it will crash, too.
Yes, because Derived is not publicly convertible to Base<Derived>, it seems
the compiler ignores the friend declaration... If you want a definite
answer what is right, I'd ask in comp.lang.c++.moderated. FWIW, compiled
with the GCC 4.1 it shows the same behaviour at runtime.
But for other reasons I can't inherit "public" in the original
application's code, it must be a "private" inheritance.
Without knowing those reasons I obviously can't comment on that. The typical
reason to use the CRTP is to add something to a class' interface, so it is
non-typical to derive privately. I'd be interested to hear the background.
I want to use dynamic_cast to reference, because I want to have an
exception, if D is not derived from Base<D>.
Shouldn't that be handled like a programming error? In that case, I'd rather
use this code here:
assert(typeid(*this) == typeid(D));
....and then use a simple static_cast<> to convert to the derived class.
Uli
OK, some more background:
In the application's code are two more classes:
First, there is a non-template base class, publicly inherited by Base<D>,
let's name it BaseBase, so Base<D> looks like this:
class BaseBase { /* a very rich public interface */ };
template< typename D >
class Base : public BaseBase
....
Private inheritance in Derived is used to reduce the public interface
inherited from BaseBase by doing something like this:
class Derived : private Base< Derived >
{
public:
using BaseBase::aFunction;
using BaseBase::anotherFunction;
using Base<Derived>::someMoreFunction;
// ...
};
So, Derived has only a reduced set of functions inherited from BaseBase and
Base<Derived>. Remeber, it's just an implementation inheritance to omit
writing a lot of stub-functions.
Second, Derived is not the last member in the inheritance chain, there is
one more, let's name it MoreDerived:
class MoreDerived : public Derived
{
// ...
};
Because of this derivation, Uli, your proposed assert will always fail:
"typeid(*this)" results to "MoreDerived", not to "Derived".
This implementation pattern is widely use in our application, which I have
to migrate from VS2003 to VS2005 (after I migrated it already from VS6.0 to
VS.NET (VS2002) and later to VS2003).
I referenced to the C++ Standard and to VS2005 C++ Breaking Changes and
found, that throwing an exception in VS2005 is correct. Microsoft has changed
runtime checking behavior to follow the C++ Standard. In down-casts using
dynamic_cast, the pointer or reference to be casted MUST be of a PUBLIC base
class!
Fine, but I have to migrate the old wrong code :-((
Georg