为什么是";这";通过函数指针调用成员函数时是否需要前缀? AFIK,在C++中,调用同一类函数中的成员中的另一个成员函数不需要“这个”前缀,因为它是隐式的。但是,在使用函数指针的特定情况下,编译器需要它。只有在通过func指针为调用包含“this”前缀时,以下代码才能正确编译-

为什么是";这";通过函数指针调用成员函数时是否需要前缀? AFIK,在C++中,调用同一类函数中的成员中的另一个成员函数不需要“这个”前缀,因为它是隐式的。但是,在使用函数指针的特定情况下,编译器需要它。只有在通过func指针为调用包含“this”前缀时,以下代码才能正确编译-,c++,this,member-function-pointers,C++,This,Member Function Pointers,当使用函数指针时,编译器能否推断它何时指向同一类的成员func class FooBar { private: int foo; public: FooBar() { foo = 100; } int GetDiff(int bar) { return abs(foo - bar); } typedef int(FooBar::*MyFuncPtr)(int); void

当使用函数指针时,编译器能否推断它何时指向同一类的成员func

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

};

f
不是
FooBar
的成员。因此,如果要对
FooBar
的实例调用
f
,必须告诉它是哪个实例


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

f
不是
FooBar
的成员。因此,如果要对
FooBar
的实例调用
f
,必须告诉它是哪个实例


在您的示例中,
f
确实包含FooBar的一个成员,但编译器不知道这一点。

这是必需的,因为成员函数指针(与函数指针不同)没有绑定,您可以将其用于不同的对象

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

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

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

调用实例成员函数时,此指针隐式地放在函数参数上。因此,当通过函数指针调用该函数时,还需要指定


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

当调用实例成员函数时,此指针隐式放置到函数参数。因此,当通过函数指针调用该函数时,还需要指定


f
不是该类的成员,而是一个局部变量,您还可以指定另一个实例指针,而不是
this
,因此编译器无法推断。对于成员函数指针,也可以作为类成员变量。

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

所以基本上当你这么做的时候

instance->foo(10);

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

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

所以基本上当你这么做的时候

instance->foo(10);

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

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

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

在指向成员的指针的情况下,过程是完全不同的。指针(不是真正的指针,而是为了参数)是通过查找找到的,但您有责任提供将调用它的对象并使用适当的运算符(用于调用引用上的成员指针的
*
,或用于调用指针上的成员的
->*


请注意,所调用的运算符是不同的,并且过程是完全不同的(在一种情况下,查找会找到一个成员,在另一种情况下,查找会找到一个恰好是指向该成员的指针的变量),但最重要的部分是,调用指向成员的指针的频率不够高,在
上调用它们的频率甚至更低,因为它不保证对小用例的语法进行豁免。

简单的问题是,这是语言设计的问题,语言就是这样设计的

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

在指向成员的指针的情况下,过程是完全不同的。指针(不是真正的指针,而是为了参数)是通过查找找到的,但您有责任提供将调用它的对象并使用适当的运算符(用于调用引用上的成员指针的
*
,或用于调用引用上的成员的
->*