本文介绍了为虚拟析构函数指定的冲突类型属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下摘录以前是在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:error:overriding'virtual aaa ::〜aaa()'
virtual _fastcall〜aaa()= 0; ///不能是抽象的
^

显然,没有bbb ::〜bbb()!

编辑



实际的类层级较大,有很多类 bbb aaa 继承,并且在它们之间存在中间成员,即bbb extends abb,它扩展了aab,从而扩展了aaa。 aaa 确实有一个抽象的虚拟析构函数,它可以在中间类中实现,但不在叶中。是的,我可以删除 __ fastcall 属性并编译。这是一个gcc限制,我无法调整调用约定吗?

是一个调用约定。



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



一些建议:


  • (例如,当与预编译的库或



The following extract was previously compiling under Borland C++, MSVC and OpenWatcom:

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

class bbb:public aaa {
};

It doesn't compile under gcc/g++ (MinGW 4.8.0). Error:

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
                     ^

Obviously, there is no bbb::~bbb()!

EDIT

The actual class hierarchy is bigger, there are many classes bbb inheriting from aaa, and there are intermediate members in between, i.e. bbb extends abb, which extends aab, which extends aaa. aaa indeed has an abstract virtual destructor, which gets implementation in the intermediate classes, but not in the leaves. Yes, I can remove the __fastcall attribute and it compiles. Is it a gcc limitation that I cannot adjust the calling convention?

解决方案

The __fastcall is a calling convention.

It's a non standard feature : the double underscore at the begin of the name means that it's implementation specific. Calling conventions are tightly related to the systems and CPU architectures. This one seems to be relevant for x86 32 bit mode.

Some recommendations:

  • You shouldn't bother with calling conventions unless absolutely required (e.g.when interfacing with precompiled libraries or extern dlls).
  • The level of optimizing that modern compilers perform does no longuer require such manual tuning. The same applies with keyword register
  • If your code really needs it on some platforms, you should foresee a #define in one of your header and make sure with conditional compilation that it's defined to nothing on platform/compilers where it's not relevant (for DLLs this approach is usual, with a library specific #define).
  • Calling conventions should be the same in all the derived classes, so it's better declared in the base class. For virtual functions this is an implicitely mandatory requirement ! Imagine that your base class passes parameters via the stack, and the derived class via the registers (fastcall). Now what code should your compiler generate if you make a polymorphic call via a base class pointer ? And what would happen if two derived classes would use different calling conventions ?
  • You can't assume that a calling convention is automatically inherited : the standard makes no guarantee, here
  • If you have to specify a calling convetion, prefer an external linkage specifier if possible (e.g. extern "C" ) because this is the only calling convention relevant semantic that is supported by the standard.

Additional information:

这篇关于为虚拟析构函数指定的冲突类型属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-11 16:43