Search code examples
c++inheritancecastingvirtual

what happened when we try to access downcasted pointer with and without virtual function


Here are 2 codes first:

#include<iostream>
using namespace std;

class A{
  public:
     virtual void  f()
    {
      cout<<"A"<<endl;
    }
};
class B: public A{
  public:
    virtual void  f()
    {
      cout<<"B"<<endl;
    }
};
int main()
{
  A* pa=new A();
  B* pb=new B();
  A* upCastpa= static_cast<A*>(pb);
  B* downCastpb=static_cast<B*>(pa);
  upCastpa->f();
  downCastpb->f();
  return 1;
}

one display

B
A

Therefore I think what really matters is the objected the pointer pointing to. However, if I remove virtual form A::f(), like this;

#include<iostream>
using namespace std;

class A{
  public:
     void  f()
    {
      cout<<"A"<<endl;
    }
};
class B: public A{
  public:
    virtual void  f()
    {
      cout<<"B"<<endl;
    }
};
int main()
{
  A* pa=new A();
  B* pb=new B();
  A* upCastpa= static_cast<A*>(pb);
  B* downCastpb=static_cast<B*>(pa);
  upCastpa->f();
  downCastpb->f();
  return 1;
}

The code will displayed A "stop" What happened? If the important thing is the objected the pointer pointing to.

it suppose to display A B instead of corrupted.

what happened?

I really appreciate any advice or instruction. Thanks a lot.


Solution

  • Irrespective of the presence or absence of virtual function:

    A* pa=new A(); 
    B* downCastpb=static_cast<B*>(pa); 
    

    causes an Undefined Behavior.

    When you use static_cast to cast an object to a type that it is not, it causes Undefined behavior. Once you have an code that produces undefined behavior it is useless to try and find reasoning for the output observed. The compiler is free to show any behavior, a crash, a weird result or an absoultely fine working code.You are completely at the mercy of the compiler.

    Reference:

    C++11 Standard 5.2.9 [expr.static.cast]

    A prvalue of type "pointer to cv1 B", where B is a class type, can be converted to a prvalue of type "pointer to cv2 D", where D is a class derived from B, if a valid standard conversion from "pointer to D" to "pointer to B" exists, cv2 is the same cv-qualification as, or greater cv-qualification than, cv1, and B is neither a virtual base class of D nor a base class of a virtual base class of D. The null pointer value is converted to the null pointer value of the destination type. If the prvalue of type "pointer to cv1 B" points to a B that is actually a subobject of an object of type D, the resulting pointer points to the enclosing object of type D. Otherwise, the result of the cast is undefined.