如果派生 class 包含额外的方法和成员,static_cast 可以从基 class 到派生 class 吗?

Can static_cast be done from base class to derived class if derived class contains additional methods and members?

假设我们有class A和B如下:

class A
{
  private:
   int a;

  public:

   void seta(int a_)
    {
       a=a_;
    }
   int geta()
   {
    return a;
   }
  };

class B: public A
{
  private:
   int b;

  public:

   int getb()
     {
       return b;
     }

  void setb()
   {
     b=geta()+1;
   }

 };

假设我在函数中编写了这样的代码:

A* a=new A();
a->seta(5);
B* b=static_cast<B*>(a);
b->setb();
cout<<b->getb()<<" and "<<b->geta()<<endl;

这段代码可以编译运行,但我不明白为什么?如果 a 是指向 A class 的指针并且在分配期间仅保留 class A 成员的内存(在运行时),为什么在静态转换之后似乎这个对象实际上是实例class B。这样操作安全吗?

[expr.static.cast]/11,强调我的:

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 (Clause 10) from B, if cv2 is the same cv-qualification as, or greater cv-qualification than, cv1. If B is a virtual base class of D or a base class of a virtual base class of D, or if no valid standard conversion from “pointer to D” to “pointer to B” exists (4.11), the program is ill-formed. The null pointer value (4.11) 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 behavior is undefined.

这样做并不安全。 下面的代码演示了为什么

#include <iostream>
using namespace std;

class A 
{
private:
  int a;

public:  
  void seta(int a_) {
    a=a_;
    cout << "seta to: " << a << endl;
  }

  int geta() {
    return a;
  }
};

class B: public A
{
  private:
   int b;

  public:

  int getb() {
    return b;
  }

  void setb() {
    b=geta()+1;
    cout << "setb to: " << b << endl;
  }  
};

int main() {

  A as[2];

  A* a1=as;
  A* a2=&as[1];

  a1->seta(5);
  a2->seta(4);

  cout << "a1: "
       << a1->geta()
       << endl;

  cout << "a2: " 
       << a2->geta()
       << endl;

  B* b=static_cast<B*>(a1);

  b->setb();

  a2->seta(3);

  cout << "b->geta(): "
       << b->geta()
       <<" and b->getb(): "  
       << b->getb()
       << endl;

  size_t sizeofa(sizeof(A));
  cout << "sizeofa: "
       << sizeofa
       << endl;

  size_t sizeofb(sizeof(B));
  cout << "sizeofb: "
       << sizeofb
       << endl;

}

输出是

seta to: 5
seta to: 4
a1: 5
a2: 4
setb to: 6
seta to: 3
b->geta(): 5 and b->getb(): 3
sizeofa: 4
sizeofb: 8