为虚拟析构函数指定的冲突类型属性

时间:2015-02-07 18:34:39

标签: c++ inheritance g++ virtual-functions calling-convention

以下摘录以前是在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扩展abb,扩展了aab,这扩展了aaa。 aaa 确实有一个抽象的虚拟析构函数,它在中间类中实现,但不在叶子中实现。是的,我可以删除__fastcall属性并进行编译。这是一个gcc限制,我无法调整调用约定吗?

1 个答案:

答案 0 :(得分:1)

__fastcall是一个调用约定。

这是一个非标准功能:名称开头的双下划线表示它是特定于实现的。调用约定与系统和CPU架构紧密相关。这个似乎与x86 32位模式有关。

一些建议:

  • 除非绝对需要(例如,与预编译库或extern dlls接口时),否则不应该使用调用约定。
  • 现代编译器执行的优化级别并不需要这样的手动调整。关键字register
  • 也是如此
  • 如果你的代码在某些平台上确实需要它,你应该在你的一个标题中预见到#define,并确保条件编译它在平台/编译器上没有任何定义(它对于DLL这个方法通常,具有特定于库的#define)。
  • 所有派生类中的调用约定应该相同,因此最好在基类中声明。对于虚拟功能,这是一个隐含的强制性要求!想象一下,您的基类通过堆栈传递参数,并通过寄存器(fastcall)传递派生类。现在,如果通过基类指针进行多态调用,编译器应该生成什么代码?如果两个派生类使用不同的调用约定会发生什么?
  • 你不能假设自动继承了一个调用约定:标准不保证,这里
  • 如果必须指定呼叫对话,会尽可能选择外部链接说明符(例如extern "C"),因为这是标准支持的唯一调用约定相关语义。

其他信息: