开发者

static_cast doubt

#include <iostream>
class A
{
public:
    开发者_运维知识库A()
    {
        std::cout << "\n A_Constructor \t" << this <<std::endl;
    }
    void A_Method()
    {
        std::cout <<"\n A_Method \t" << this <<std::endl;
    }
};
class B:public A
{
public:
    B()
    {
        std::cout <<"\n B_Constructor \n";
    }
    void B_Method()
    {
        std::cout <<"\n B_Method \t" << this <<std::endl;
    }
};

int main()
{
    A *a_obj = new A;
    B *b_obj = static_cast<B*> (a_obj);  // This isn't safe.
    b_obj->B_Method();      
    getchar();
    return 0;
}

OUTPUT :

A_Constructor 001C4890

B_Method 001C4890

As no run-time check isn't involved in type conversion, static_cast isn't safe. But in this example, I got what I didn't even expect. Since there is no call to B::B(), any of it's members should not be able to get called by b_obj. Despite that I got the output.

In this simple case, I might have succeeded though it is known unsafe. My doubts are -

  • Though there is no call to B::B(), how was I able to access class B member functions.
  • Can some one please provide an example, where this is unsafe and might get wrong( though what I given before might serve as a bad example, but even better).

I did it on Visual Studio 2010 and with \Wall option set.


This is Undefined Behavior. Sometimes UB causes crashes. Sometimes it seems to "work". You are right that you shouldn't do this, even though in this case less bad things happened.


What you are trying is undefined behaviour so ANYTHING could happen. This seems to work (and probably works) fine as you don't try to access any data members (you don't have any). Try to add some data members to both classes and access it from methods, you will see that behaviour will change to completely unpredictable.


I doubt that this particular case is UB. First, it just casts a pointer from one type to another. Since there is no virtual/multiple inheritance involved, no pointer adjustment is performed, so basically the pointer value stays the same. Surely it points to an object of a wrong type, but who cares, as long as we don't access any B members, even if there were some? And even if there was pointer adjustment involved, it would still be okay if we didn't access any memory pointed by it, which we don't.

Then, the example calls a method of B. Since it is not virtual, it just a normal function call with the hidden argument this (think B::B_Method(this)). Now, this points to an object of a wrong type, but again, who cares? The only thing it does is print it, which is always a safe thing to do.

In fact, you can even call methods using a NULL pointer. It works as long as the method isn't virtual and doesn't try to access anything pointed by this. I once had a library used by many programs. This library had a singleton-like class which had to be constructed explicitly, but none of the programs actually did it. The instance pointer was initialized to NULL by default, as it was global. It worked perfectly since the class had no data members at all. Then I added some and all the programs suddenly started to crash. When I found out the reason, I had a really good laugh. I've been using an object that didn't even exist.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜