C++ C型铸造导致SIGILL,动态_铸造正常
在我的一个项目中,我有一个实现四个接口的类:C++ C型铸造导致SIGILL,动态_铸造正常,c++,g++,C++,G++,在我的一个项目中,我有一个实现四个接口的类: class A : public B, public C, public D, public E { ----Implementation Code here---- }; 这四个接口只包含纯虚拟函数,没有一个构成菱形问题(因此我不需要使用virtual关键字),因此我在执行类似操作时没有发现任何问题: A* var = new A; ((C*)var)->method_from
class A : public B,
public C,
public D,
public E
{
----Implementation Code here----
};
这四个接口只包含纯虚拟函数,没有一个构成菱形问题(因此我不需要使用virtual关键字),因此我在执行类似操作时没有发现任何问题:
A* var = new A;
((C*)var)->method_from_interface();
然而,一些丑陋的事情正在发生,因为函数正在跳转到一个类的不同方法,valgrind抱怨未处理的指令。然而,这样做:
A* var = new A;
(dynamic_cast<C*>(var))->method_from_interface();
注意,我知道在这段时间里,D*实际上是A*,所以对B*进行A转换并没有违反任何规则。虽然我不能静态转换它,因为D*和B*没有关系,但我可以成功地使用reinterpret\u cast。C样式转换只是对指向类的指针进行“基本”内存映射。如果您的方法在类中是offset=42,则会使(*(A+42))()(当然是简化的) 但是,如果从多个类继承,则必须考虑不同的类以及编译器放置它们的顺序 静态_cast考虑了多重继承 在您的示例中,它可能与B、C、D或E一起使用,但与其他的不一起使用。但是,您没有充分的理由这样做:您将调用
A->methodFromInterface()
,它就可以工作了
在C++上,建议使用静态的CAST或动态的CAST(注意:第二个依赖于RTTI,可能不可用),丢弃旧的C型CAST。
编辑
试图复制问题,但无法,可以在上找到文件
- 类别2.hpp:
- class2.cpp:
- class.cpp:
g++ -fno-rtti -o truc ./class.cpp ./class2.cpp && ./truc
C-style cast只是对指向类的指针进行“基本”内存映射。如果您的方法在类中是offset=42,则会使(*(A+42))()(当然是简化的) 但是,如果从多个类继承,则必须考虑不同的类以及编译器放置它们的顺序 静态_cast考虑了多重继承 在您的示例中,它可能与B、C、D或E一起使用,但与其他的不一起使用。但是,您没有充分的理由这样做:您将调用
A->methodFromInterface()
,它就可以工作了
在C++上,建议使用静态的CAST或动态的CAST(注意:第二个依赖于RTTI,可能不可用),丢弃旧的C型CAST。
编辑
试图复制问题,但无法,可以在上找到文件
- 类别2.hpp:
- class2.cpp:
- class.cpp:
g++ -fno-rtti -o truc ./class.cpp ./class2.cpp && ./truc
问题在于你的职能是做些什么 这行很好:
D* iface = p->recoverItemByName("nameThatReturnsClassA");
但这条线是坏的,因为B和D无关,所以你不能安全施放。尝试调用static_cast(iface),您将看到编译器在抱怨-这应该是一个警告
((B*) iface)->call_method_from_b_iface();
在上一行中,您正在编写iface不仅指向D,而且指向a的知识。最好将a指针存储到a并使用该指针。我也是
A* iface = p->recoverItemByName("nameThatReturnsClassA");
iface->call_method_from_b_iface();
如果您仍然想坚持使用D*iface,那么可以这样编写代码(两个选项中只有一个选项):
D*iface=p->recoverItemByName(“namethatturnsclassa”);
静态投影
<>最后但并非最不重要:尽量避免旧的C风格的演员阵容,总是尝试使用C++风格的CaskStupe,StistaCase/DyrimCyCaseand RealTytPraseCask(按这个顺序)。
这行很好:
D* iface = p->recoverItemByName("nameThatReturnsClassA");
但这条线是坏的,因为B和D无关,所以你不能安全施放。尝试调用static_cast(iface),您将看到编译器在抱怨-这应该是一个警告
((B*) iface)->call_method_from_b_iface();
在上一行中,您正在编写iface不仅指向D,而且指向a的知识。最好将a指针存储到a并使用该指针。我也是
A* iface = p->recoverItemByName("nameThatReturnsClassA");
iface->call_method_from_b_iface();
如果您仍然想坚持使用D*iface,那么可以这样编写代码(两个选项中只有一个选项):
D*iface=p->recoverItemByName(“namethatturnsclassa”);
静态投影
最后但并非最不重要:尽量避免旧的C风格的演员阵容,总是尝试使用C++风格的演员StaskSCAST,StistaCype/DyrimCype演员和RealTurkType演员(按这个顺序)。
注意,我知道在这个时候,D*实际上是A*,所以
对B*进行选角并没有违反任何规则
错
您可能知道它实际上是一个A*,但编译器不知道,至少在编译时,当它试图找出要发出什么代码来进行转换时是这样
当您使用虚拟方法从多个类继承时,会发生一件有趣的事情。当您从派生类转换为某个接口类时,指针地址将发生更改!编译器对指针进行调整,使其对您声明的指针类型有效。你自己试试,从一个A*
指针开始显示它的值,然后转换到AB*
,C*
,和D*
并显示它们。最多一个基类与A*
相同,其他基类则不同
当您使用C样式转换时,您告诉编译器“我不管您是否能正确地进行转换,无论如何都要这样做。”它会将D*
适当地视为B*
,而不进行所需的修正,因此现在指针完全错了。它没有指向类B vtable,因此调用了错误的方法
动态_cast之所以有效,是因为它使用了运行时可用的额外信息;它可以将指针跟踪到其最派生的A*
,然后返回到AB*
注意,我知道在这个时候,D*实际上是A*,所以
对B*进行选角并没有违反任何规则
错
您可能知道它实际上是一个A*,但编译器不知道,至少在编译时,当它试图找出要发出什么代码来进行转换时是这样
A