2014-03-05 127 views
6

common.h向前声明的类的成员函数指针Test和功能接收一个成员函数指针:向前声明的类

class Test; 

void func(const Test &t, int (Test::*f)() const, int x, int y); 

在源文件target.cpp,我定义函数,使得

#include "common.h" 

void func(const Test &t, int (Test::*f)() const, int x, int y) { 
    std::cout << "f: " << (t.*f)() << ", x: " << x << ", y: " << y << std::endl; 
} 

在我的主文件中,我定义了类Test并使用函数func

class Test { 
public: 
    int example() const { return 1; } 
}; 

#include "common.h" 

int main() { 
    Test t; 
    func(t, &Test::example, 0xaaaaaaaa, 0xbbbbbbbb); 
    return 0; 
} 

显然这有点臭,因为指向成员函数的指针有时不仅仅是一个简单的指针。但由此产生的行为有点压倒性:给定的参数0xaaaaaaaa0xbbbbbbbb将不会正确传递给函数。或者更确切地说,功能func解释给定的堆栈不同于调用者将数据压入堆栈。 f的大小取决于该类是只是前向声明还是实际定义的。与Visual Studio 2013编译的输出是:

f: 1, x: 0, y: 2130567168 

我想,如果一个向前声明就足够了,它真的不要紧是否有给予与否的定义。

+0

“0xaaaaaaaa”和“0xbbbbbbbb”不能表示为“int”(在windows调用约定下,请参见[MSDN](http://msdn.microsoft.com/zh-cn/library/296az74e.aspx))。缩小转换调用未定义的行为。您是否尝试过使用较小的数字? – Mankarse

+0

我选择这些值是为了在我的堆栈中清楚地看到它们。当然,如果您选择较小的值,它也不起作用。我认为,缩小是在编译期间完成的,因为这些值是文字并且绑定到整数值。 – phlipsy

+0

恕我直言,它是不正确的,因为这个函数可能是虚拟或不虚拟 – borisbn

回答

4

默认情况下,MSVC有利于指向成员的速度超过正确性。您可以通过传递编译器标志/vmg来强制它按照标准工作。

+0

哦,那太棒了!我在这个问题上失去了一整天。 – phlipsy

+0

@phlipsy同样的事情发生在我身上(即我也很难学会这个标志)。 – Angew

+0

你有这方面的一些额外的信息,链接等? – phlipsy