我以前认为成员函数只是普通函数的一个特例,其中成员函数在'this'指针的参数列表的开头有一个额外的参数,即成员函数所在的对象应该采取行动.我以前用这种方式使用了boost :: function,从未遇到过任何问题:
boost::function f<(void)(MyObject*, int, int)> = &MyObject::method_that_takes_two_ints;
但我已经看到了成员函数指针的这种语法:
void (MyObject::*f)( int, int ) = &MyObject::method_that_takes_two_ints;
在此语法中,'this'参数不可见.这让我想知道引擎盖指针到成员函数是否真的是一个单独的野兽,而且这种提升正在为我处理细节.
标准规定了'this'参数的位置是什么?也许只是在我的编译器上,额外的'this'参数首先出现,也许在其他编译器上它可能在最后?我很幸运,我的思维方式与我的编译器(GCC4,VS2005)如何处理它一致?指向成员函数的指针总是只是带有额外参数的指针到函数的特殊情况,或者编译器能够以不同的方式实现它们吗?
该标准几乎没有说明this
指针应放在何处,事实上,对成员函数使用不同的调用约定是相当普遍的.(所以'this'指针不只是一个额外的第一个参数,它实际上存储在与第一个arg通常不同的位置)
特别是,MSVC使用thiscall
成员函数的调用约定和stdcall
其他地方.
http://www.hackcraft.net/cpp/MSCallingConventions/#thiscall描述了它们之间的差异,但请注意,thiscall
将this
指针存储在ECX
寄存器中,同时stdcall
将所有参数存储在堆栈中.
你最好将它们视为完全不同的类型.指向一个成员函数是不是只是一个指向一个额外的参数的函数.
该this
指针不沿着一个指针存储部件(成员函数指针是这种特殊情况).如果你这样做
void (MyObject::*f)( int, int ) = &MyObject::method_that_takes_two_ints;
然后存储的只是在objet上调用哪个成员函数的信息,您稍后必须提供该信息.如果你想调用它,你必须传递一个对象,编译器将从中获取this
指针.
MyObject o; (o.*f)(1, 2);
成员函数指针只是一个成员指针,其类型(指向的)是一个函数类型.标准说成员函数指针没有自己指向的"成员函数类型",并且会以某种方式包含this指针类型.
int main() { typedef void fun() const; fun MyObject::*mem_function_ptr = &MyObject::const_method_that_takes_two_ints; }
fun
在该代码中是函数类型."正常"函数具有的类型.与成员函数指针相反,指向函数的指针只是指向具有该类型的函数的指针:
void foo() { cout << "hello"; } int main() { typedef void fun(); fun * f = &foo; }
指向成员函数的指针在该函数类型的顶部具有附加成员指针级别.
关于this
指针及其与指向的对象的关系(不是技术,只是理论上的东西):
每个成员函数都有一个隐藏参数,称为implicit object parameter
具有类型MyObject&
或MyObject const&
取决于您是否具有const或nonconst成员函数.你呼吁成员函数的对象,o
是的implied object argument
,这是传递给参数.在构成描述如何调用成员函数的规则的标准理论中,隐式对象参数是第一个隐藏参数.这是概念性的,并不意味着它是实现中的真实案例.隐含的对象参数然后绑定到该隐式对象参数,可能导致隐式转换(因此,如果在非const对象上调用const成员函数,则限定转换将转换MyObject
为MyObject const&
.这就是使非const函数比const函数调用更好的选择,对于非const对象来说.例如,可以在此代码中说:
struct A { operator int() const { return 0; } }; int main() { A a; int i = a; // implicit conversion using the conversion function }
a
类型的隐含对象参数A
绑定到类型的隐式对象参数A const&
,其对象随后由this
具有此类型的指针指向A const*
.需要注意的是,隐式对象参数只是一个理论构造,用于形式化构成调用成员函数的规则(构造函数不包含它们),而this指针实际上是存在的.this
是一个指针,因为在this
介绍时,C++还没有引用.
我希望这能帮助你理解这件事.
关于成员函数指针的优秀文章是CodeProject的成员函数指针和最快可能的C++代表.本文介绍了从简单案例到具有多重继承的虚拟成员函数指针的成员函数指针.作为奖励,它提供了一个非常有用的代表实现.