C++中类成员函数指针详解

原文出处:点击打开链接

      在C++中类成员函数指针是一种比较特别的指针,尽管直接使用类成员函数的情况不太多,但是还是有必要详解一下这类指针。

      具体语法

      首先说明一下类成员函数指针的声明方式:

      

Return_Type (Class_Name::* pointer_name) (Argument_List);
 
Return_Type:   member function return type.
Class_Name:    name of the class in which the member function is declared.
Argument_List: member function argument list.
pointer_name:  a name we'd like to call the pointer variable.
      通过函数指针调用类成员函数需要使用操作符.*或者->*,具体使用参考下面这段代码:

#include <iostream>
#include <string>
using std::string;
 
class Foo{
public:
  int f(string str){
    std::cout<<"Foo::f()"<<std::endl;
    return 1;
  }
};
 
int main(int argc, char* argv[]){
  int (Foo::*fptr) (string) = &Foo::f;
  Foo obj;
  (obj.*fptr)("str");//call: Foo::f() through an object
  Foo* p=&obj;
  (p->*fptr)("str");//call: Foo::f() through a pointer
}

    类成员函数指针不是一般的指针

    通常的函数指针指向的地址都是一个准确的代码入口地址,但是不难想象类成员函数指针指向的应该是一个相对的位置(相对于整个类的偏移地址)。这一点很好证明。
    类中的静态函数实际和全局函数一样,有着确定的入口地址,类成员静态函数没有this指针,但是却可以共享整个类的命名范围,也可以访问到类中的其他成员。现在来看下面这段代码:
#include <iostream>
#include <string>
using std::string;
 
class Foo{
public:
  static int f(string str){
    std::cout<<"Foo::f()"<<std::endl;
    return 1;
  }
};
 
int main(int argc, char* argv[]){
  //<pre name="code" class="cpp">int (Foo::*fptr) (string) = &Foo::f;//error

int (*fptr) (string) = &Foo::f;//correct (*fptr)("str");//call Foo::f()}
 其中  
int (Foo::*fptr) (string) = &Foo::f;//error
会引起如下错误:
cannot convert 'int (*)(std::string)' to 'int (Foo::*)(std::string)
这说明了类成员函数指针不是一般的函数指针

    类成员函数指针的转换

   还是先来看看下面的代码:

#include <iostream>
class Foo{
public:
  int f(char* c=0){
    std::cout<<"Foo::f()"<<std::endl;
    return 1;
  }
};
 
class Bar{
public:
  void b(int i=0){
    std::cout<<"Bar::b()"<<std::endl;
  }
};
 
class FooDerived:public Foo{
public:
  int f(char* c=0){
    std::cout<<"FooDerived::f()"<<std::endl;
    return 1;
  }
};
 
int main(int argc, char* argv[]){
  typedef  int (Foo::*FPTR) (char*);
  typedef  void (Bar::*BPTR) (int);
  typedef  int (FooDerived::*FDPTR) (char*);
 
  FPTR fptr = &Foo::f;
  BPTR bptr = &Bar::b;
  FDPTR fdptr = &FooDerived::f;
 
  //bptr = static_cast<void (Bar::*) (int)> (fptr); //error
  fdptr = static_cast<int (Foo::*) (char*)> (fptr); //OK: contravariance
 
  Bar obj;
  ( obj.*(BPTR) fptr )(1);//call: Foo::f()
}
 
Output:
Foo::f()

语句:

bptr = static_cast<void (Bar::*) (int)> (fptr);无法正常执行,因为非静态、非虚的类成员函数指针都是属于强类型,所以无法进行转换。

但是语句

fdptr = static_cast<int (Foo::*) (char*)> (fptr);可以执行,这是因为两者所属的类存在继承关系。

Bar obj;
<p>  ( obj.*(BPTR) fptr )(1);//call: Foo::f()可以执行,因为fptr是静态绑定的</p>



    虚成员函数指针

#include <iostream>
class Foo{
public:
  virtual int f(char* c=0){
    std::cout<<"Foo::f()"<<std::endl;
    return 1;
  }
};
 
class Bar{
public:
  virtual void b(int i=0){
    std::cout<<"Bar::b()"<<std::endl;
  }
};
 
class FooDerived:public Foo{
public:
  int f(char* c=0){
    std::cout<<"FooDerived::f()"<<std::endl;
    return 1;
  }
};
 
int main(int argc, char* argv[]){
  typedef  int (Foo::*FPTR) (char*);
  typedef  void (Bar::*BPTR) (int);
  FPTR fptr=&Foo::f;
  BPTR bptr=&Bar::b;
 
  FooDerived objDer;
  (objDer.*fptr)(0);//call: FooDerived::f(), not Foo::f()
 
  Bar obj;
  ( obj.*(BPTR) fptr )(1);//call: Bar::b() , not Foo::f()
}
 
Output:
FooDerived::f()
Bar::b()

    通过上面的代码可以发现,类成员函数指针同样可以实现多态!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值