C++类成员函数如何赋值给函数指针

C++类成员函数如何赋值给函数指针,第1张

完善了一下。

#include<iostream>

using namespace std;

class Ca{

public:

int max(int a,int b)

{

return a>ba:b;

}

};

int (Ca::p)(int,int);

int main()

{

p=&Ca::max;

Ca a;

cout<<(ap)(2,3);

system("pause");

return 0;

}

C++指向函数指针定义方式为:

  返回类型

(指针名)(函数参数列表),例如

void

(p)(int)是指向一个返回值为void

参数为int类型的函数。

  而若想定义一个指向类成员函数的函数指针该怎么定义呢?对成员函数指针的使用。

  (1)非静态成员函数

  定义方式:返回类型

(类名::指针名)(函数参数列表)例如void

(A::p)(int)是一个指向A类中成员函数的函数指针。

  赋值方式:p=&A::函数名,而一般的函数指针的赋值是p=函数名即可,注意区别。(成员函数必须是public类型的)

  调用方式:成员函数指针的调用必须通过类对象进行调用,ap(int)即可调用成员函数(该成员函数是public类型的)

  (2)静态成员函数

  对于静态成员函数的定义和使用方法都与普通函数指针的相同,只是在赋值的时候和非静态成员们函数指针的赋值方法相同。

  因为静态成员函数的指针类型是与普通函数指针类型相同的。

1一个指向外部函数的指针声明为: void(pf)(char,constchar); void strcpy(char dest,constchar source); pf=strcpy; 2一个指向类A成员函数的指针声明为: void(A::pmf)(char,constchar);

基类指针

对其自己的成员函数:随便访问

对子类成员函数:不可访问(对于虚函数,都是子类的指针对子类重写的新的虚函数的引用,或者未重写时候,父类的虚函数的引用,父类即使用指针引了虚函数,也是引自己的)

可以的,不过要间接访问。看下面的例子

#include <iostream>

using std::cout;

using std::endl;

class A{

 int data;

 public: A(int i):data(i)

 {

  cout<<"new"<<endl;

  };

  A():data(0)

  {

   cout<<"new A"<<endl;

  }; 

  A(const A& a){

   data=adata;

   cout<<"new A copy"<<endl;

  }; 

  ~A()

  {

   cout<<"delete"<<endl;

  };

  static void access(Aa)//静态成员,参数为对象指针

  {

   a->data++;

   cout<<a->data<<endl;//通过指针访问内部非静态对象;但不能用this指针直接来访问

  }

 };

 

 int main()

 {

     A b(2);

     baccess(&b);//静态成员函数访问

     return 0;

 }

首先 函数指针是指向一组同类型的函数的指针;而类成员函数我们也可以相似的认为,它是指向同类中同一组类型的成员函数的指针,当然这里的成员函数更准确的讲应该是指非静态的成员函数。前者是直接指向函数地址的,而后者我们从字面上也可以知道 它肯定是跟类和对象有着关系的。

函数指针实例:

代码如下:

typedef int (p)(int,int);//定义一个接受两个int型且返回int型变量的函数指针类型

int func(int x,int y)

{

printf("func:x=%d,y=%d/n",x,y);

return (x<yx:y);

}

int main()

{

p fun=func;//定义函数指针并给它赋上一个函数指针

cout<<"min:"<<(fun)(4,5)<<endl;//为什么fun需要用()扩起来呢因为的运算符优先级比()低,如果不用()就成了(fun())

return 0;

}

而“指向类成员函数的指针”却多了一个类的区别:

class A

{

public:

int func(int x,int y)

{

printf("A::func:x=%d,y=%d/n",x,y);

return (x<yx:y);

}

};

typedef int (A::p)(int,int);//指针名前一定要加上所属类型类名 A::的限定

int main()

{

p fun=&A::func;

A a; //因为成员函数地址的解引用必须要附驻与某个对象的地址,所以我们必须创建某个对象。

cout<<"min:"<<(afun)(4,5)<<endl;

return 0;

}

嘿嘿。。只是用起来 感觉怪怪滴。

接下来 我们可以再扩展一下下:

代码如下:

#include <tcharh>

#include <iostream>

#include <stdioh>

using namespace std;

class A

{

public:

int func1(int x,int y)

{

printf("A::func:x=%d,y=%d/n",x,y);

return (x<yx:y);

}

virtual int func2(int x,int y)

{

printf("A::func:x=%d,y=%d/n",x,y);

return (x>yx:y);

}

};

class B:public A

{

public:

virtual int func2(int x,int y)

{

printf("B::func:x=%d,y=%d/n",x,y);

return (x+y);

}

};

typedef int (A::p)(int,int);//指针名前一定要加上所属类型类名 A::的限定

typedef int (B::p0)(int,int);

int main()

{

A a; //因为成员函数地址的解引用必须要附驻与某个对象的地址,所以我们必须创建某个对象。

p fun=&A::func1;

cout<<(afun)(4,5)<<endl;

cout<<(bfun)(4,5)<<endl<<endl;

fun=&A::func2;

cout<<(afun)(4,5)<<endl;//请注意这里调用的是虚函数,嘿嘿 还真神奇 类成员函数指针也支持多态。

cout<<(bfun)(4,5)<<endl<<endl;

//fun=&B::func2; //这样式错误滴,因为不存在派生类的"指向类成员函数的指针"到基类的"指向类成员函数的指针"的隐式转换

fun=(int (A::)(int,int))&B::func2;//应该进行强制转换

cout<<(afun)(4,5)<<endl;

cout<<(bfun)(4,5)<<endl<<endl;

p0 fun0=&B::func2;

cout<<(afun)(4,5)<<endl;

cout<<(bfun)(4,5)<<endl<<endl;

fun0=&A::func2; //正确,因为这里进行了隐式转换

cout<<(afun)(4,5)<<endl;

cout<<(bfun)(4,5)<<endl<<endl;

//从上面我们不难发现 指向类成员函数的指针基类和派生类的关系和指向类对象的指针基类和派生类的关系完全相反,

//基类成员函数的布局被认为是派生类成员函数布局的一个子集

return 0;

}

接下 是有关模板类的类成员函数指针的使用

实例如下:

代码如下:

#include <tcharh>

#include <iostream>

#include <stdioh>

using namespace std;

class A

{

public:

int func(int x,int y)

{

printf("A::func : x=%d,y=%d/n",x,y);

return (x<yx:y);

}

};

class B

{

public:

int func(int x,int y)

{

printf("B::func : x=%d,y=%d/n",x,y);

return (x>yx:y);

}

};

template<class T>

class C

{

public:

T c;

void Print()

{

int (T::p)(int,int)=&T::func;

(cp)(4,5);

}

};

int main()

{

C<A> ca;

C<B> cb;

caPrint();

cbPrint();

return 0;

}

从上面 可以很清晰地看到。。其实它和普通的模板没有什么区别。。只不过将限定名称该为参数名酒OK啦。。。

通常不建议这样做哦。这样做通常意味着设计上有严重的缺陷。

因为:静态成员函数是不需要类的对象就可以调用的。类的对象都不存在当然不能直接调用了。

如果一定要调用,你可以用以下三种方式,创建一个类对象在进行调用

1、用参数传递进一个内的对象;

2、在静态成员函数中创建一个临时对象。

3、创建一个该类的全局对象

仅举一例

#include <iostream>

#include <cassert>

using namespace std;

class A{

public:

 void foo()

 {

     cout << "Yes" << endl;

 }

 static void boo()

 {

   static A oneObj;

   oneObjfoo();

 }

};

int main(){

 A::boo();

 A::boo();

 return 0;

}

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/12156519.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-21
下一篇2023-05-21

发表评论

登录后才能评论

评论列表(0条)

    保存