reinterpret_cast和不相关类型之间的虚拟

时间:2012-03-27 10:47:36

标签: c++ virtual reinterpret-cast

有人会解释为什么下面的代码有效,我在Visual Studio .NET 2008上测试过它,在Cygwin和ideone.com上测试g ++。更重要的是我想知道它是否有效。请注意,AB是不相关的类型。

编辑:关注@ leftaroundabout的评论我对我的代码进行了以下更改

#include <iostream>
#include <cstdlib>

class A
{
public:
    virtual void Bar()
    {
        std::cout << "A::Bar() -> " << this << std::endl;
    }

    virtual void Foo()
    {
        std::cout << "A::Foo() -> " << this << std::endl;
    }   
};

class B
{
public:
    virtual void Foo()
    {
        std::cout << "B::Foo() -> " << this << std::endl;
    }
};

int main()
{
    B* b = reinterpret_cast<B*>( new A );
    b->Foo();   
    return EXIT_SUCCESS;
}

程序输出消息:

A::Bar() -> 0x9806008

基本上,无论调用什么,都会调用第一个虚方法。

4 个答案:

答案 0 :(得分:3)

它只是运气好,标准中没有任何内容表明它应该有效 - 演员阵容无效。编译器很可能在内存中以完全相同的方式布置这两个类,但AFAIK没有这样的义务。

尝试添加:

virtual void Bar()
{
    std::cout << "A::Bar() -> " << this << std::endl;
}
Foo A之前的

,看看会发生什么 - 运行Bar时可能会调用b->Foo()

答案 1 :(得分:1)

reinterpret_cast<>基本上会关闭任何类型的安全检查并告诉编译器“不要检查这个,我知道我在做什么。”

Microsoft's page on reinterpret_cast告诉它以及任何人;

  

reinterpret_cast的结果无法安全地用于任何事情   除了被回归到原来的类型。其他用途是,在   最好,不便携。

答案 2 :(得分:0)

无效;取消引用已被强制转换为错误类型的指针会产生未定义的行为。

在这种情况下,它似乎起作用,因为两个对象都具有匹配的虚函数,并且编译器恰好以相同的方式为每个对象布置虚拟调度元数据。虽然大多数编译器可能会这样做,但它没有指定,也不能依赖。

答案 3 :(得分:0)

来自标准5.2.10 / 7

  

指向对象的指针可以显式转换为指向的指针   不同类型的对象.65)除了转换类型的右值   “指向T1的指针”到“指向T2的指针”(其中T1和T2为   对象类型以及T2的对齐要求为否   比T1更严格,并回到原来的类型产生   原始指针值,这种指针转换的结果是   未指定的。

这意味着唯一保证的是,如果你将A转换为B然后再回到A,你会得到原始指针:

  A* a = reinterpret_cast<A*>(reinterpret_cast<B*>( new A ));
  a->Foo();  //Ok

所有其他用途均未指定。