为什么通过函数指针调用成员函数时需要“this”前缀?

时间:2012-06-26 17:06:47

标签: c++ this member-function-pointers

AFAIK,在C ++中,在同一个类的函数成员中调用另一个成员函数不应该需要“this”前缀,因为它是隐式的。但是,在使用函数指针的特定情况下,编译器需要它。仅当我通过func指针 -

包含调用的“this”前缀时,以下代码才能正确编译

当使用函数指针时,编译器在指向同一个类的成员函数时会推断出它吗?

class FooBar 
{
private: 
    int foo;

public:  

    FooBar()
    {
        foo = 100;
    }

    int GetDiff(int bar)
    {
        return abs(foo - bar);
    }

    typedef int(FooBar::*MyFuncPtr)(int); 

    void FooBar::Bar()
    {       
        MyFuncPtr f = &FooBar::GetDiff;
        (this->*f)(10);
        GetDiff(10);
    }

};

5 个答案:

答案 0 :(得分:6)

这是必需的,因为成员函数指针(与函数指针不同)没有绑定,你可以将它们与不同的对象一起使用。

(this->*f)(10);
(foo.*f)(10);
// etc.

答案 1 :(得分:2)

当你调用实例成员函数时,这个指针被隐含地放到函数参数中。因此,当通过函数指针调用该函数时,您还需要指定this

f不是该类的成员,而是一个局部变量,您也可以指定另一个实例指针而不是this,因此编译器无法推断出它。成员函数指针与类成员变量相同。

答案 2 :(得分:1)

简单的问题是语言设计是一个问题,而语言就是这样设计的。

在成员函数内部,当编译器遇到标识符时,为了简化 common 语法,它会从这个类开始执行查找(加上参数上的ADL),如果查找找到一个明确的非这种类型的静态成员(或基类型)然后编译器将为您注入this->(即,将operator->应用于this指针。

在指向成员的指针的情况下,该过程是完全不同的。指针(实际上不是指针,但为了参数)是通过查找找到的,但是你有责任提供它将被调用的对象并使用适当的运算符(.*为{}在引用上调用指向成员的指针,或者在->*上调用指针上的成员。)

请注意,被调用的运算符是不同的,并且该进程完全不同(在一种情况下,查找找到一个成员,在另一种情况下,它找到一个恰好是指向成员的指针的变量),但是最多重要的是调用指向成员的指针很少,并且在this上调用它们的频率更低,因此它不能保证对小用例的语法进行豁免。

答案 3 :(得分:0)

f不是FooBar的成员。因此,如果您想在f的实例上调用FooBar,则必须告诉它实例。

在您的示例中,f 包含 FooBar的成员,但编译器不知道。

答案 4 :(得分:0)

这是因为C ++运行时在您不看的时候处理类的方式。 基本上,将函数指针存储在实例中是低效的,因此编译器构建一个特定于类的表,其中的函数指针与您定义的成员函数具有相同的arity,并且在运行时传递this指针(AFAIK visualc通过通过ecx指针,我不完全确定GCC会发生什么)

所以基本上当你做

instance->foo(10);

您告诉运行时使用参数10调用函数foo并传递(实例)作为此指针,这就是为什么您必须明确说明必须调用哪个对象的原因。