为什么是";这";通过函数指针调用成员函数时是否需要前缀? AFIK,在C++中,调用同一类函数中的成员中的另一个成员函数不需要“这个”前缀,因为它是隐式的。但是,在使用函数指针的特定情况下,编译器需要它。只有在通过func指针为调用包含“this”前缀时,以下代码才能正确编译-
当使用函数指针时,编译器能否推断它何时指向同一类的成员func为什么是";这";通过函数指针调用成员函数时是否需要前缀? 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
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->
(即,将运算符->
应用于此
指针)
在指向成员的指针的情况下,过程是完全不同的。指针(不是真正的指针,而是为了参数)是通过查找找到的,但您有责任提供将调用它的对象并使用适当的运算符(用于调用引用上的成员指针的*
,或用于调用引用上的成员的->*
)