以下摘录之前是在 Borland C++、MSVC 和 OpenWatcom 下编译的:
class aaa {
virtual _fastcall ~aaa();
};
class bbb:public aaa {
};
它不能在 gcc/g++ (MinGW 4.8.0) 下编译。错误:
probz.cpp:7:7: error: conflicting type attributes specified for 'virtual bbb::~bbb()' class bbb:public aaa { ^ probz.cpp:3:20: error: overriding 'virtual aaa::~aaa()' virtual _fastcall ~aaa()=0;///can't be abstract ^
显然,没有 bbb::~bbb()!
编辑
实际的类层次结构更大,有很多bbb类继承自aaa,中间还有一些中间成员,即bbb extends abb,它extends aab,延伸 aaa。 aaa 确实有一个抽象的虚拟析构函数,它在中间类中得到实现,但在叶子中没有。是的,我可以删除 __fastcall
属性并进行编译。我不能调整调用约定是 gcc 的限制吗?
最佳答案
__fastcall
是一个调用约定。
这是一个非标准功能:名称开头的双下划线表示它是特定于实现。调用约定与系统和 CPU 架构密切相关。这似乎与 x86 32 位模式有关。
一些建议:
- 除非绝对需要(例如,当与预编译库或 extern dlls 交互时),否则您不应该为调用约定而烦恼。
- 现代编译器执行的优化级别不再需要此类手动调整。这同样适用于关键字
register
- 如果您的代码在某些平台上确实需要它,您应该在其中一个 header 中预见到
#define
并确保通过条件编译它在不相关的平台/编译器上没有定义(对于 DLL,这种方法很常见,使用特定于库的#define
)。 - 所有派生类的调用约定应该相同,因此最好在基类中声明。对于虚函数,这是一个隐含的强制要求!想象一下,您的基类通过堆栈传递参数,派生类通过寄存器传递参数(fastcall)。现在,如果您通过基类指针进行多态调用,您的编译器应该生成什么代码?如果两个派生类使用不同的调用约定会怎样?
- 您不能假设调用约定是自动继承的:标准在此处不做任何保证
- 如果您必须指定调用约定,请尽可能首选外部链接说明符(例如
extern "C"
),因为这是唯一与调用约定相关的语义受标准支持。
附加信息:
关于c++ - 为虚拟析构函数指定的冲突类型属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28385849/