问题
Is there a way to control the order of some classes methods in the vfptr? It seems that Visual C++ 2010 at least puts the method pointers in the declaration order, except for overloaded methods. Below is sample code:
enum ENUM {
};
class CLASS {
virtual void foo1() { };
virtual CLASS& __cdecl operator<<(const ENUM x) { return *this; };
virtual void foo2() { };
virtual CLASS& __cdecl operator<<(const char* x) { return *this; };
virtual CLASS& __cdecl operator<<(int x) { return *this; };
virtual void foo3() { };
virtual void foo1(int x) { };
};
int main() {
CLASS c;
return 0;
}
The above code generates following vfptr:
[0] 0x00e21091 CLASS::foo1(int) *
[1] 0x00e2100a CLASS::foo1(void) *
[2] 0x00e211ae CLASS::operator<<(int) *
[3] 0x00e21050 CLASS::operator<<(char const *) *
[4] 0x00e211db CLASS::operator<<(enum ENUM) *
[5] 0x00e2106e CLASS::foo2(void) *
[6] 0x00e21172 CLASS::foo3(void) *
So the overloaded methods get grouped to first such declaration and then reversed. Having them grouped together isn't a problem, since I can group them in the header file easily. However the reverse order is a problem as different compilers apparently won't do that which means they will call wrong methods. This is related to passing object pointers between application and a DLL.
First I hoped MSVC has a preferred order for overloaded methods, so I tried to declare the methods in the order MSVC had them in the vfptr, but then it simply reversed them again, here's the code and result of that:
class CLASS {
virtual void foo1(int x) { };
virtual void foo1() { };
virtual CLASS& operator<<(int x) { return *this; };
virtual CLASS& operator<<(const char* x) { return *this; };
virtual CLASS& operator<<(const ENUM x) { return *this; };
virtual void foo2() { };
virtual void foo3() { };
};
result:
[0] 0x0113100a CLASS::foo1(void) *
[1] 0x01131091 CLASS::foo1(int) *
[2] 0x011311db CLASS::operator<<(enum ENUM) *
[3] 0x01131050 CLASS::operator<<(char const *) *
[4] 0x011311ae CLASS::operator<<(int) *
[5] 0x0113106e CLASS::foo2(void) *
[6] 0x01131172 CLASS::foo3(void) *
I'd like to use method overloading, there's at least one hack I could use (know the order MSVC will use, create new header with that order to be used only by the DLLs), but I'd rather get it to work properly in the first place. Or is it at all possible?
回答1:
You can use C++ interfaces between modules even with different compilers but you have just bumped into an edge case. Here is why do interfaces work across different compilers: Usable C++ compilers must produce code that works with COM interfaces. A COM object looks quite like a C++ object with a single vtable whose pointer is at offset zero of the object. The problem is that COM doesn't define any rules for overloaded methods as far as I know but as long as you don't want to exploit method overloading and maybe some other exotic language features then you can trust method order (because of the COM compatibility).
Even if you don't use C++ interfaces between modules your interface between modules should be reasonably simple. I was never in burning need of method overloads in an interface between modules. Even if you needed an overload you can give the methods separate names just like in languages where you don't have overloading at all. Passing primitive types and simple data structures between modules is also wise, if you pass only primitive types then it is very easy to compile modules with different configs (like one in Debug and the others in Release) to speed up debugging iterations.
来源:https://stackoverflow.com/questions/22059092/visual-c-methods-in-vfptr-in-reverse-order