问题
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?
回答1:
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:
- __cdecl, __stdcall, and other usual calling conventions
- Calling convetions demistified
来源:https://stackoverflow.com/questions/28385849/conflicting-type-attributes-specified-for-virtual-destructor