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

Conflicting type attributes specified for virtual destructor

以下摘录之前是在 Borland C++、MSVC 和 OpenWatcom 下编译的:

class aaa {
    virtual _fastcall ~aaa();
};

class bbb:public aaa {
};

它不能在 gcc/g++ (MinGW 4.8.0) 下编译。错误:

probz.cpp:7:7: 错误:为 'virtual bbb::~bbb()' 指定的类型属性冲突
 class bbb:public aaa {
       ^
probz.cpp:3:20: 错误:覆盖 'virtual aaa::~aaa()'
   virtual _fastcall ~aaa()=0;///不能抽象
                     ^

很明显,没有bbb::~bbb()!

编辑

实际的class层级更大,有很多classes bbb继承自aaa,并且在它们之间有中间成员,即 bbb 扩展了 abb,它扩展了 aab,它扩展了 aaa。 aaa 确实有一个抽象的虚拟析构函数,它在中间 classes 中实现,但不是在叶子中。是的,我可以删除 __fastcall 属性并进行编译。我不能调整调用约定是gcc的限制吗?

__fastcall是一个调用约定。

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

一些建议:

  • 除非绝对需要(e.g.when 与预编译库交互或 extern dlls),否则您不应该为调用约定而烦恼。
  • 现代编译器执行的优化级别不再需要此类手动调整。这同样适用于关键字 register
  • 如果您的代码在某些平台上确实需要它,您应该预见到 header 中的一个 #define 并确保通过条件编译它在 platform/compilers 上没有定义在不相关的地方(对于 DLL,这种方法很常见,特定于库 #define)。
  • 所有派生的 class 中的调用约定应该相同,因此最好在基础 class 中声明。对于虚函数,这是隐含的强制要求!想象一下,您的基础 class 通过堆栈传递参数,而派生的 class 通过寄存器(快速调用)传递参数。现在,如果您通过基本 class 指针进行多态调用,您的编译器应该生成什么代码?如果两个派生的 classes 使用不同的调用约定会发生什么?
  • 您不能假定调用约定是自动继承的:标准不作任何保证,此处
  • 如果您必须指定调用约定,如果可能,最好使用外部链接说明符(例如 extern "C" ),因为这是唯一与调用约定相关的语义受标准支持。

附加信息: