casting problem with virtuals

Hi all, I have a problem where my derived class is losing its state data. some isolated code is below, the problem manifests itself in CClassD::DoExtras().

CClassA and CClassC exist in our old codebase and CClassB and CClassD are derived for our new variant of the codebase.

thanks for looking


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
class CClassA
{
	public:
		int dataA;
};


class CClassB : public CClassA
{
	public:
		int dataB;
};

//---------------------------------

class CClassC
{
public:
	void DoSomething(CClassA& ref)
	{
		// blah...
		DoExtras(ref);
	}

	virtual void DoExtras(CClassA& ref)
	{
		// blah
	}
}


class CClassD : public CClassC
{
public:
	void DoSomething(CClassA& ref)
	{
		// blah blah...
		CClassC::DoSomething(ref)
	}
	
	virtual void DoExtras(CClassA& ref)
	{
		CClassB& b = reinterpret_cast<CClassB&>(ref);
		int i = b.data; // ouch! b.data is uninitialised
	}
}

//--------------------------------------

void otherCode()
{
	CClassB myB;
	myB.dataB = 99;

	CClassD myD;
	myD.DoSomething(myB);
}

Last edited on
int i = b.data; // ouch! b.data is uninitialised
Do you mean dataA or dataB?

I think you should be using static_cast instead of reinterpret_cast because reinterpret cast will not handle if CClassA is stored at an later offset in CClassB.
In general prefer using a virtual function over a cast down the hierarchy.

If you have to do a down-cast, prefer a dynamic down-cast.

If for some reason, you have to perform a compile-time cast, the right cast in this case is a static_cast<> , not a reinterpret_cast<>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <typeinfo>

struct A
{
    virtual ~A() {}
    virtual int get_it() const { return i ; }
    int i = 3 ;
};

struct B : A
{
    virtual int get_it() const override { return A::get_it() + j ; }
    int j = 5 ;
};

int foo( const A& a ) { return a.get_it() ; }

int bar( const A& a )
{
    int result = a.i ;

    try
    {
        const B& b = dynamic_cast< const B& >(a) ;
        result += b.j ;
    }
    catch( const std::bad_cast& ) { /* this is not a B */ }

    return result ;
}

int main()
{
    A a ;
    std::cout << foo(a) << ' ' << bar(a) << '\n' ;

    B b ;
    std::cout << foo(b) << ' ' << bar(b) << '\n' ;

}

http://ideone.com/mMvt8Q
static_cast worked great thankyou both.

@Peter87, it was supposed to be dataB

In general prefer using a virtual function over a cast down the hierarchy.


I couldn't agree more.
Unfortunately CClassB has a virtual dtor() but no virtual methods so dynamic cast fails with a compiler error.


edited "virtual methods"
Last edited on
> Unfortunately CClassB has a virtual dtor() but no virtual methods so dynamic cast fails with a compiler error.

A virtual destructor is sufficient to make the class a polymorphic type.

The dynamic down-cast from CClassA gives an error because CClassA is not a polymorphic type. Add a virtual destructor for CClassA and the error will go away.
@JLBorges

my mistake, CClassB has a virtual dtor() but CClassA doesn't and i dont have write access to it.

I guess thats the root of the problem.

it's all working now though :)
Topic archived. No new replies allowed.