# C++ Type Casting safety?

This topic is 4612 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi, i have something like this:
class A{};
class B: public A{
public:
char b[32];
bool valid;
B(){valid=true;}
};

class C: public A{
public:
int c;
bool valid;
C(){valid=true;}
};

std::vector <A *>v;
B *b=new B();
C *c=new C();
v.push_back((A *)b);
v.push_back((A *)c);


Is it then safe to check if the object's type is B or C by doing:
if(((B *)v.at(0)).valid==true)
//class=B
if(((C *)v.at(0)).valid==true)
//class=C


I don't think so but it does work (Debug and Release mode MSVC++ 6.0), as long as the classes are different enough so the compiler can't cast them by itself. Is this safe or is there a safer or official way? Thanks.

##### Share on other sites
No, it's not safe. The proper way is as follow:

class A{public:   virtual ~A() = 0 {}    // A needs a virtual destructor for polymorphic behavior};class B: public A{public:    char b[32];};class C: public A{public:    int c;};std::vector <A *>v;B *b=new B();C *c=new C();v.push_back(b);    // Casts from B to A are unnecessaryv.push_back(c);    // Casts from C to A are unnecessary

B* ptr_b = dynamic_cast<B*>(v.at(0));if(ptr_b == NULL) {    /* that was not a B */ }else{   /* that was a B */   ptr_b->b[0] = 42;}

However, it is preferable to directly rely on virtual functions placed in A (and thus shared between B and C), because using type queries like that requires that you add up a test for each new type in your hierarchy, which is brittle, and also is rather inefficient.

##### Share on other sites
You probably want to use RTTI and a dynamic_cast.

Edit: Doh, beaten.

##### Share on other sites
I tried using dynamic_cast but it gives an exception in KERNEL32.DLL at that line as class A is polymorphic. Adding the virtual destructor didn't solve it.

Quote:
 However, it is preferable to directly rely on virtual functions placed in A (and thus shared between B and C)...

That's true and that's how i intended it in the first place but i need this in a few special cases.

Edit: I think i'll just add a virtual function returning the type, overridden by derived classes.

##### Share on other sites
The problem arises if you actually have an A* in your vector. When you typecast the A* to a B* and acces the valid member, you are accessing memory you don't own. The correct way would be to have an enumerated type or some type of flag in the base class.

enum ObjectType { OBJ_A, OBJ_B, OBJ_C };class A{    ObjectType type;    A() : type(OBJ_A) { }};class B : public A{    B() : A() { type = OBJ_B; }}class C : public A{    C() : A() { type = OBJ_C; }}

And as somebody said before, you will definately want virtual destructors if you are creating any memory in any of your derived classes.

Edit: Its okay to "play" with memory by typecasting. But you have to be absolutely certain you aren't overstepping your bounds. In your original class B, you declared a char[32] then the bool valid. In the original class C you declared an int c then the bool valid. This puts (valid) at a different location depeneding on which class the ptr is actually pointing to. So your original implementation is never safe because if you had a B* and changed b[4] to one, it would appear as though ((C*)&some_B)->valid would be true.

##### Share on other sites
Quote:
 Original post by blaze02The correct way would be to have an enumerated type or some type of flag in the base class.

That's unsafe: the flag or enumerated type could be set incorrectly because of human error, while dynamic_cast works on any class that uses inheritance (and thus, has a virtual destructor). And it's also more difficult to manage an inheritance lattice with only enumerated types, while dynamic_cast will handle type lattices without a sweat.

There are other ways, for instance using virtual functions as a semantic replacement for dynamic_cast, which need about as much work as an enumeration-based system, but are type-safe and can handle lattices. Still, they rely on human intervention and as such are prone to semantic bugs.

Of course, the best way (and the one that is the most often available and thrust forward in OOP) would be to use virtual functions to represent operations, and rework the design so the inheritance tree fits together better.

##### Share on other sites
Quote:
 I tried using dynamic_cast but it gives an exception in KERNEL32.DLL at that line as class A is polymorphic. Adding the virtual destructor didn't solve it.

Did make sure you have RTTI switched on?

##### Share on other sites
Quote:
Original post by Nitage
Quote:
 I tried using dynamic_cast but it gives an exception in KERNEL32.DLL at that line as class A is polymorphic. Adding the virtual destructor didn't solve it.

Did make sure you have RTTI switched on?

Ah no thanks! I thought it was on by default. It works now, thanks for all help.

##### Share on other sites
RTTI... ick... so... slow.

Its not like it does any optimizations, it just embeds a lot of junk in the code so it knows which object is of which type.

##### Share on other sites
Did you run a test to see if using RTTI really makes a noticeable speed difference in a sample program? IMO, while it will have some impact, it's hardly going to slow your program to a crawl.

1. 1
Rutin
37
2. 2
3. 3
4. 4
5. 5

• 11
• 10
• 13
• 104
• 11
• ### Forum Statistics

• Total Topics
632978
• Total Posts
3009681
• ### Who's Online (See full list)

There are no registered users currently online

×