interpret_cast和virtual在不相关的类型之间
reinterpret_cast and virtual between unrelated types
有人能解释一下为什么下面的代码有效吗?我已经在Visual Studio.NET 2008、Cygwin和ideone.com上测试过它。更重要的是,我想知道它是否有效。注意,A
和B
是不相关的类型。
编辑:跟随@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
基本上,无论调用什么,都会调用第一个虚拟方法。
它只是运气好,标准中没有任何内容表明它应该工作——强制转换无效。编译器可能会在内存中以完全相同的方式布置两个类,但不存在AFAIK这样的义务。
尝试添加:
virtual void Bar()
{
std::cout << "A::Bar() -> " << this << std::endl;
}
在A
中的Foo
之前,看看会发生什么——b->Foo()
运行时很可能会调用Bar
。
reinterpret_cast<>
基本上关闭任何类型的安全检查,并告诉编译器"不要检查这个,我知道我在做什么。"
微软在relpret_cast上的页面告诉它和任何人一样好;
interpret_cast的结果不能安全地用于任何事情而不是被铸造回其原始类型。其他用途包括,在最好,不可移植。
无效;取消引用被强制转换为错误类型的指针会产生未定义的行为。
在这种情况下,它似乎可以工作,因为两个对象都有匹配的虚拟函数,而编译器恰好以相同的方式为每个对象布置虚拟调度元数据。虽然大多数编译器可能都会这样做,但它没有指定,也不能依赖。
来自标准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
所有其他用途均未指明。
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 类中的字符串不命名类型
- 不完整类型错误(E0409、E0070、E0515)
- CRTP 单一实例不完整类型或非文本类型
- 如果条件不相关,我应该更喜欢两个 if 语句而不是 if-else 语句吗?
- 使用具有结构不完整类型错误的模板
- 将积分类型的数组作为另一个不相关的积分类型的阵列进行访问的安全且符合标准的方法
- 强制转换为不相关的引用类型是否违反严格的别名规则?
- 与 2 个相关类一起无效使用不完整类型
- 对类型 'A *' 的非常量左值引用不能绑定到不相关的类型 'std::shared_ptr<A>' 的值
- 将不相关类型的对象reinterpret_cast空类是未定义的行为吗?
- C++中的类型转换:相关类型和不相关类型
- 与两个(看似)不相关的类型匹配的模板
- 当将不相关类型定义为别名时,对函数的调用是不明确的
- 对类型 '_wrap_iter<pointer>' 的非常量左值引用无法绑定到不相关类型的值
- interpret_cast和virtual在不相关的类型之间
- MISRA C++ 2008 违反规则 5-2-7:不得直接或间接将指针类型的对象转换为不相关的指针类型
- 我应该更喜欢mixin还是函数模板来将行为添加到一组不相关的类型中
- 针对不相关类型的动态调度的解决方案
- 将函数的返回值类型转换为大小相同的不相关类型