dynamic_cast and static_cast

Started by
9 comments, last by Fruny 19 years, 8 months ago
Alright, so I learned a new trick... Using dynamic_cast to access child-class methods from a parent class and using static_cast to access parent-class methods from a child class.

class CParent
{
public:
    virtual void Init()
    {
        printf("CParent::Init()\n");
    }
};

class CChild : public CParent
{
public:
    virtual void Init()
    {
        printf("CChild::Init()\n");
    }
};

void use_dynamic_cast()
{
    CParent *pParent = new CParent;
    CChild *pChild = new CChild;
    pParent->Init();    // call CParent::Init()
    pChild->Init();     // call CChild::Init()
    pParent = dynamic_cast<CParent *> (pChild);
    pParent->Init();    // call CChild::Init() from pParent
}

void use_static_cast()
{
    CParent *pParent = new CParent;
    CChild *pChild = new CChild;
    pParent->Init();    // call CParent::Init()
    pChild->Init();     // call CChild::Init()
    pChild = static_cast<CChild *> (pParent);
    pChild->Init();     // call CParent::Init() from pChild
}


I was wondering, are there any other interesting things that can be done by using dynamic_cast and static_cast? -noix-
In this world gone mad, we won't spank the monkey; the monkey will spank us.
Advertisement
Quote:Original post by noixtirdoe
pParent = dynamic_cast<CParent *> (pChild);
pParent->Init(); // call CChild::Init() from pParent

That's kind of a waste of time. It's equivalent to: pChild->CParent::Init(); except that really, really braindead compilers might do the latter version more efficiently.
void use_dynamic_cast(){    CParent *pParent = new CParent;    CChild *pChild = new CChild;    pParent->Init();    // call CParent::Init()    pChild->Init();     // call CChild::Init()    pParent = dynamic_cast<CParent *> (pChild);    pParent->Init();    // call CChild::Init() from pParent}


Output:
CParent::Init()
CChild::Init()
CChild::Init()

void use_dynamic_cast(){    CParent *pParent = new CParent;    CChild *pChild = new CChild;    pParent->Init();    // call CParent::Init()    pChild->Init();     // call CChild::Init()    pChild->CParent::Init();}


Output:
CParent::Init()
CChild::Init()
CParent::Init()

Your version doesnt achieve the same effect mine does.

-noix-

EDIT:
However, the use of static_cast to get a pointer back to the parent class is unneeded because then your trick of pChild->CParent::Init() works instead.
In this world gone mad, we won't spank the monkey; the monkey will spank us.
Quote:Original post by noixtirdoe
*** Source Snippet Removed ***

Output:
CParent::Init()
CChild::Init()
CChild::Init()

-noix-


Well you don't need to use any cast to assign a child to a parent pointer/reference to achieve that, also 2 phase construction is bad thing what i mean by that is having a constructor that does half or no intialization then a init method to finish it.
UH-OH!!

why you use classes and inheritance at all when you want to call functions that way.

Also what you do with your
pChild = static_cast<CChild *> (pParent);
is totally go around that little bit type security c++ brings to you.

only use static_cast if you KNOW 100% the object is the type you cast it to.

in your example of static cast i would expect behavior of the program will go insane if you define a second function to the CChild class. you MAY have luck and all goes like you want, but reordering the functions can already be the thing that brings your system out of balance...

-----The scheduled downtime is omitted cause of technical problems.
Here I added a print() function to the CChild class. After I cast a pointer to the parent class (which we already determined was not needed due to pChild->CParent::Init()), would you assume the pChild would try to call the parent class' method of print() only to find it doesnt exist? No, it actually calls CChild::print(). As far as I can tell, doing this doesnt make the program unstable because everything runs perfectly. But like everyone else has said, the call to static_cast isnt needed.

void use_static_cast(){    CParent *pParent = new CParent;    CChild *pChild = new CChild;    pParent->Init();    // call CParent::Init()    pChild->Init();     // call CChild::Init()    pChild = static_cast<CChild *> (pParent);    pChild->Init();     // call CParent::Init() from pChild    //pChild->CParent::Init();    pChild->print();}


In this world gone mad, we won't spank the monkey; the monkey will spank us.
Quote:Original post by noixtirdoe
As far as I can tell, doing this doesnt make the program unstable because everything runs perfectly. But like everyone else has said, the call to static_cast isnt needed.


You cannot assume that casting from a parent pointer to a child when calling child's methods doesn't make things unstable if you don't know what type of instance the parent pointer is refering to, it could be a sibling of "child" this all really depends on what member function does, any ways thats the whole point of using dynamic_cast to navigate type hierarchies that will give you an indication of navigation failure. static_cast just does blind cast so only use it when your absolutely sure of the type of the instance it refers to.
Quote:Original post by snk_kid
Quote:Original post by noixtirdoe
As far as I can tell, doing this doesnt make the program unstable because everything runs perfectly. But like everyone else has said, the call to static_cast isnt needed.


You cannot assume that casting from a parent pointer to a child when calling child's methods doesn't make things unstable if you don't know what type of instance the parent pointer is refering to, it could be a sibling of "child" this all really depends on what member function does, any ways thats the whole point of using dynamic_cast to navigate type hierarchies that will give you an indication of navigation failure.


Okay, that makes better sense, thanks :D
In this world gone mad, we won't spank the monkey; the monkey will spank us.
There's a nice trick you can do but I can't remember, anyone like to help out.

Basically if you have:[cpp]class parent
{
...
};

class Child1 : public Parent
{
...
};

class Child2 : public Parent
{
...
};[/cpp]Then you have some way from a pointer to a Parent Object, of seeing if it's actually a Child1 object for example. We used macros in the class definition I think and then we'd use it to to the same thingfor every physics body unless it was a player car to alter the physics.
pParent = dynamic_cast<CParent *> (pChild);

You don't need an explicit cast there. Just do

pParent = pChild;

The assignment is legal because the parent type only restricts what operations can be invoked on the object. I can't believe this hasn't been said yet.. And what resource is noixtirdoe using to learn C++ to not know this, yet already be learning about dynamic_cast..

This topic is closed to new replies.

Advertisement