vfptr中的Visual C ++方法以相反的顺序 [英] Visual C++ methods in vfptr in reverse order

查看:49
本文介绍了vfptr中的Visual C ++方法以相反的顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有一种方法可以控制vfptr中某些类方法的顺序?似乎Visual C ++ 2010至少将方法指针按声明顺序放置,但重载方法除外.下面是示例代码:

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;
}



上面的代码生成以下vfptr:



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)    *



因此,重载的方法将被分组为首先进行此类声明,然后反向进行.将它们分组在一起不是问题,因为我可以轻松地将它们分组在头文件中.但是相反的顺序是一个问题,因为不同的编译器显然不会这样做,这意味着它们将调用错误的方法.这与在应用程序和DLL之间传递对象指针有关.
首先,我希望MSVC具有重载方法的首选顺序,因此我尝试按MSVC在vfptr中具有它们的顺序声明这些方法,但随后它又再次将它们反向,这是代码和结果:



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() { };
};


结果:

[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)    *



我想使用方法重载,至少可以使用一种技巧(知道MSVC将使用的顺序,以该顺序创建新的标头,以仅由DLL使用),但是我希望它能够正常工作首先.还是有可能?



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?

推荐答案

即使在使用不同的编译器的情况下,您也可以在模块之间使用C ++接口,但您刚刚遇到了麻烦.这就是为什么接口可以在不同的编译器上工作的原因:可用的C ++编译器必须生成与COM接口一起使用的代码.COM对象看起来很像具有单个vtable的C ++对象,其指针位于该对象的偏移量为零.问题是,据我所知,COM并未为重载方法定义任何规则,但是只要您不想利用方法重载以及其他某些外来语言功能,那么您就可以信任方法顺序(因为COM兼容性).

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).

即使您在模块之间不使用C ++接口,模块之间的接口也应该相当简单.我从不迫切需要模块之间的接口中的方法重载.即使您需要重载,也可以为方法指定单独的名称,就像根本没有重载的语言一样.在模块之间传递基本类型和简单的数据结构也是明智的,如果仅传递基本类型,则很容易用不同的配置(例如Debug中的一个和Release中的其他)编译模块,以加快调试迭代的速度.

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.

这篇关于vfptr中的Visual C ++方法以相反的顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆