2

I am reviewing C++ casts operator and I have the following doubt:

for polymorphic classes

  • I I should use polymorphic_cast
  • I should never use of static_cast since down-casting might carry to undefined behavior. The code compiles this case anyway.

Now suppose that I have the following situtation

class CBase{};
class CDerived : public CBase{};

int main( int argc, char** argv ){
    CBase* p = new CDerived();
    //.. do something
    CDerived*pd = static_cast<CDerived*>( p );
}

Since there is no polymorphism involved I will not use polymorphic_cast and the code will not even compile.

If at some point, someone introduces some virtual functions in the inheritance tree and I am now aware of it so I am in danger: how can I realize it?

I should move to polymorphic_cast to avoid any risk, but the code will be still compiling without any notification.

What do you do to realize about such kind of changes or prevent these case?

Thanks AFG

Abruzzo Forte e Gentile
  • 14,423
  • 28
  • 99
  • 173
  • *and the code will not even compile* - do you mean *and the code will compile fine*? – Björn Pollex Oct 25 '10 at 08:38
  • 1
    Shouldn't the destructor be `virtual` for CBase ? In that case you can use `dynamic_cast` or `polymorphic_cast`. – Naveen Oct 25 '10 at 08:40
  • 2
    There is no such thing as `polymorphic_cast` in standard C++. Why don't you use a `CDerived` in the first place? Or if you think you have to use dynamic allocation, why don't you use a `CDerived*`? Virtual functions do not pose any danger even when you're unaware of them. And what are all those "C" prefixes on class names? It sounds like a severe case of stuttering to me. Cheers, – Cheers and hth. - Alf Oct 25 '10 at 08:46
  • :( yeah..I mean dynamic_cast not boost::polymorphic_cast. This last it is implemented using a dynamic_cast with the difference that throws a std::bad_cast if the dynamic_cast returns 0. Today I need couple of more cofees to wake up. – Abruzzo Forte e Gentile Oct 25 '10 at 09:37
  • P.S. I like the idea/suggestion of adding virtual to destructors as starting point of every class and use dynamic_cast – Abruzzo Forte e Gentile Oct 25 '10 at 09:40

3 Answers3

3

Background you didn't include - boost has polymorphic_cast as a wrapper around dynamic_cast<> that throws when the cast fails. static_cast<> is fine if you're certain that the data is of the type you're casting to... there is no problem with or without virtual members, and the code you include saying it won't compile will compile and run just fine as is.

I guess you're thinking about the possibility to accidentally cast to another derived class? That's the utility/danger of casting, isn't it? You can add a virtual destructor then use dynamic_cast<>, as strictly speaking RTTI is only available for types with one or more virtual functions.

Code written with static_cast<> will continue to handle the same type safely irrespective of the introduction of virtual functions... it's just that if you start passing that code other types (i.e. not CDerived or anything publicly derived therefrom) then you will need the dynamic_cast<> or some other change to prevent incompatible operations.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • Hi Tony! I like this idea. Putting virtual to destructor by default will prevent my issue and at the same time I will have no leakage at all. Thanks a lot! – Abruzzo Forte e Gentile Oct 25 '10 at 09:49
  • @abruzzo-forte-e-gentile: I know many people choose to do this (virtual destructors by default), but be aware that there is some cost in this. It's small, but I'd say you should only resort to making destructors virtual if you expect the class to be used polymophically (i.e, at least one other method is also declared virual). – beldaz Oct 28 '10 at 03:00
1

While you deal with pointer p (of type CBase*) the pointed object will be treated as a CBase, but all virtual functions will do the right thing. Pointer pd treats the same object as a CDerived. Upcasting in this way is dangerous since, if the object is not derived from the upcasted type, any extra member data for the upcasted object will be missing (meaning you'll be poking around in some other data), and virtual function lookup will be all messed up. This is the opposite to downcasting (as you've tagged this question) where you might get slicing.

To avoid this you need to change your programming style. Treating the same object as two different types is a dubious practice. C++ can be very good at enforcing type safety, but it will let you get away with nasty things if you really want to, or just don't know better. If you are wanting to do different things depending upon an object type, and can't do it through virtual functions (such as through double dispatch), you should look more thoroughly into RTTI (look here, or see some good examples here).

Community
  • 1
  • 1
beldaz
  • 4,299
  • 3
  • 43
  • 63
0

polymorphic_cast is not defined in C++. Are you thinking about dynamic_cast?

Anyway, you can not do anything to prevent it.

BЈовић
  • 62,405
  • 41
  • 173
  • 273