C ++中不同类树之间的转换

时间:2011-11-29 10:29:02

标签: c++ casting

下面的代码似乎与编译器一起使用(在Linux和Mac OS上都是clang,g ++)我试过,但它是否能保证总能做到人们所期望的呢?

struct A {
  virtual void foo() = 0;
};

struct A2 {
  virtual void foo() = 0;
};

struct B : public A2 {
  void foo() {
    printf("test\n");
  }
};

int main() {
  B* b = new B;
  ((A*)b)->foo();
}

我意识到这是不好的做法,不应该这样做,但它是否一般有效?

3 个答案:

答案 0 :(得分:6)

如果人们期望未定义的行为,则可以保证。

答案 1 :(得分:4)

实践并不错: 工作。它会做某事。不太可能,崩溃。由于您正在调用unspecified behaviour,因此全部允许。 编辑您可以参考编译器技术文档(参考ABI )查找您可能依赖的特定于编译器的扩展

尝试使用

static_cast<A*>(b)    // invalid static cast (compile error)
dynamic_cast<A*>(b)   // returns null pointer value (runtime)

你正在做的是有效的

  • reinterpret_cast<A*>(b)

并且结果完全您自己的责任 实现定义

编辑致Nawaz:相关标准段落:§5.2.10,条款

  

7. 指向对象的指针可以显式转换为指向不同对象类型的指针。 69 当a   “指向T1的指针”类型的 prvalue v将转换为“指向 cv T2的指针”类型,如果两者都是T1,则结果为static_cast<cv T2*>(static_cast<cv void*>(v))和T2是标准布局类型(3.9)和对齐   T2的要求不比T1严格。将“指向T1的指针”类型的 prvalue 转换为“指向T2的指针”类型(其中T1和T2是对象类型,T2的对齐要求不比T1更严格)并返回原始类型产生原始指针值。 任何结果   其他此类指针转换未指定

答案 2 :(得分:3)

如果您使用C ++风格的演员表,那么您会立即看到问题:

(static_cast<A*>(b))->foo();  //compile-time error
(dynamic_cast<A*>(b))->foo(); //runtime error

演示:http://ideone.com/LZjrx(编译时错误)
演示:http://ideone.com/ePIfO(运行时错误)

由于static_cast会出现编译错误,故事会在编译时结束。当dynamic_cast时,则转换返回null,您尝试调用foo,因此会出现运行时错误。

即使你不知道要使用哪个强制转换,这两个强制转换也足以让人怀疑代码,而reinterpret_cast的使用是如此罕见,我甚至不在这考虑。