Topic: dynamic_cast to C of hierarchy D protected: C public B: public A


Author: nospam@nospam.com
Date: Mon, 18 Dec 2000 17:51:57 GMT
Raw View
    Given the code below, in which functions having accessibility to all
classes attempt to use dynamic_cast<C*> to obtain a C pointer from an A
pointer to an object that is actually a D, and get a null pointer, should
the result be different according to the standard, particularly since a
down-cast to D and then an (implicit) up-cast to C does work?
    The situation (in its original form) comes about as a result of using
ostream/streambuf, in which a derived stream tries to check that rdbuf()
returns a pointer to a C, but in which the actual C is really a D derived
(protected); the down-caster is a friend of both the C and D classes.
    The compiler used was Visual C++ 6.0, but I think gcc gives the same
result.
    If the standard really does specify this behavior, should that standard
be changed, since the alternative is something of a kluge, e.g. making C
aware of D, or something similar?
    Thanks in advance,
    David
P.S. My email address can be obtained by changing the anti-spam address at
the end of this sentence as follows: cycle each letter back one in the
alphabet and change the underscores to at-sign and period, respectively:
dqmvtqmvt_bum-joum_dpn.

Output:
pB = 00000000
pC = 00000000
pD = 0012FF14
pC = 0012FF14
pB = 00000000
pC = 00000000
pD = 0012FF14
pC = 0012FF14

Source code of simplified example:
#include <iostream>
using namespace std ;
class C;
class A
{
public:
    inline virtual ~A(){}
    friend void DynCastTest();
    friend class C ;
    friend class D ;
    friend class B ;
};
class B: public A
{
    friend void DynCastTest();
    friend class C ;
    friend class B ;
    friend class D ;
};
class C: public B
{
    friend class D ;
    friend class B ;
    friend class A ;
    friend void DynCastTest();
    int m_intC ;
public:
    static void testCast();
};
class D: protected C
{
    int m_intD ;
public:
//   ~D(){}
    friend void DynCastTest();
    friend void C::testCast();
    friend class C ;
    friend class B ;
    friend class A ;
};
void C::testCast()
{
    D d1 ;
    A * pA = &d1 ;
    B * pB = dynamic_cast< B *>( pA );
    C * pC = dynamic_cast< C *>( pA );
    D * pD = dynamic_cast< D *>( pA );

    cout << "pB = " << (void*)pB << endl ;
    cout << "pC = " << (void*)pC << endl ;
    cout << "pD = " << (void*)pD << endl ;
    pC = pD ;
    cout << "pC = " << (void*)pC << endl ;
    pC->m_intC = 123 ;
}
void DynCastTest()
{
    D d1 ;
    A * pA = &d1 ;
    B * pB = dynamic_cast< B *>( pA );
    C * pC = dynamic_cast< C *>( pA );
    D * pD = dynamic_cast< D *>( pA );

    cout << "pB = " << (void*)pB << endl ;
    cout << "pC = " << (void*)pC << endl ;
    cout << "pD = " << (void*)pD << endl ;
    pC = pD ;
    cout << "pC = " << (void*)pC << endl ;
}
int main()
{
    DynCastTest();
    C::testCast();
    return 0 ;
}

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]