下面的代码似乎与编译器一起使用(在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();
}
我意识到这是不好的做法,不应该这样做,但它是否一般有效?
答案 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的指针”类型的 prvaluev
将转换为“指向 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
的使用是如此罕见,我甚至不在这考虑。