首先感谢大神在我的博客里提的问题,跟bolow一起探讨得到了下面的答案。
首先看下面的程序:
1 #include2 using namespace std; 3 class A 4 { 5 public: 6 int i; 7 A():i(0){}; 8 int foo(){ return i;} 9 };10 11 class B12 {13 public:14 int j,k;15 B():j(1),k(2){}16 int foo(){ return k;}17 };18 19 typedef int (B::*BFPTR)();20 int main()21 {22 int (A::*fptr)()= &A::foo;23 BFPTR bfptr1=(BFPTR) fptr;24 B b;25 A a;26 cout<<(b.*bfptr1)()<
22 int (A::*fptr)()= &A::foo; 将A函数的foo地址给以A为类的一个函数指针23 BFPTR bfptr1=(BFPTR) fptr; 告诉编译器把上面的函数指针当作B的函数指针来看(A的函数指针转为B的函数指针)24 B b;25 A a;26 cout<<(b.*bfptr1)()<
这里引出一个事实:所谓的类根本就没有成员函数一说,从内存布局上也能看出来,内存布局中只有成员变量的空间,并没有成员函数的内存空间。
这是为什么呢? 那就需要知道成员函数到底是怎么被调用的。
我们看成员函数的调用:对象.成员函数() 或 对象指针->成员函数()
那成员函数实际上是如何被编译器声明的呢? 成员函数(类, 参数) 比如我们有以下的类:
1 class A{2 public:3 void foo(int a, int b){4 5 }6 private:7 int value;8 };
其实上面的类其实是像下面声明的:
1 class A{2 private:3 int value;4 };5 6 void foo(void *ptr, int a, int b){7 8 }
当我们调用a.foo(1, 2)时,其实是下面的形式:
1 void foo(void *ptr, int a, int b){...
可见,所谓的.运算符实际是把this指针传递给函数foo了。
那我们最开始的第一个程序里为什么会输出1呢?因为成员函数返回一个成员变量时,只是返回对象的首地址的偏移值。所以,返回了第一个参数1。
如果A类有三个参数,函数foo返回第三个参数时,那输出结果就不是所能预料的了。