如果派生类包含其他方法和成员,那么static_cast可以从基类到派生类完成吗?

时间:2017-01-29 13:26:40

标签: c++ static-cast

假设我们有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 A成员的内存(在运行时),那么为什么在静态转换之后看起来这个对象实际上是{{1的实例}}。这是安全的操作吗?

2 个答案:

答案 0 :(得分:3)

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

  

类型为“指向 cv1 B的指针”的prvalue,其中B是类类型,可以转换为类型为“指向的指针的prvalue” cv2 D“,其中DB派生的类(第10条),如果 cv2 与cv资格相同,或更高的cv资格, cv1 。如果BD的虚拟基类或虚拟基类D的基类,或者没有从“指向D的指针”到“指向B”的指针存在(4.11),程序格式不正确。空指针值(4.11)将转换为目标类型的空指针值。如果“指向 cv1 B的指针”的prvalue指向实际上是B类型的对象的子对象的D,则生成的指针指向到D类型的封闭对象。 否则,行为未定义。

答案 1 :(得分:0)

这不是一件安全的事情。 以下代码说明了原因

#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