向普通函数传递类成员函数指针的问题 c 成员函数指针

将一个类成员函数的函数指针传递给另一个成员函数是比较简单的,只要定义一个函数指针就可以轻松实现。示例如下:

#include <iostream>
using namespace std;

class test
{
public:
typedef void (test::*pFUN)();
void func1()
向普通函数传递类成员函数指针的问题 c 成员函数指针
{
func2(&test::func3);//把func3的指针传递给func2
}
void func2(pFUN pfun)
{
(this->*pfun)();
}
void func3()
{
cout<<"testfunc3."<<endl;
}
};

main()
{
void (test::*pfun)() =&test::func3; //把func3的指针赋给pfun

test my_test;
my_test.func1();
my_test.func2(pfun); //把pfun传递给func2
cin.get();
}

输出结果为:
test func3.
test func3.

但是,如果直接把类成员函数的函数指针作为参数传递给一个外部的普通函数(__cdecl),比如把上面的test类的func3传递给下面的函数:
void fun(void (*pfun)());
编译器就会报错。这是因为类的成员函数是绑定到对象的,对于不同的对象,成员函数将会产生不同的拷贝,这样编译器就不知道把哪个拷贝传给fun了。这种情况在很多地方都会遇到,比如OpenCV里面的鼠标事件回调函数:
void cvSetMouseCallback( const char* window_name, CvMouseCallbackon_mouse, void* param CV_DEFAULT(NULL));
如果第二个参数是类的成员函数m_class::on_mouse(),那么直接传递就会失败。
解决这个问题的方法,目前我所了解的有四种:
(1)把这个类改成普通的函数。这是最笨的办法。写成类的好处是可以在成员函数之间共享一些数据,如果改成普通的函数,那么就可能会定义一些全局变量来实现共享,而且也不便于管理。
(2)直接把要传递的函数声明为static类型,比如:
static void func3();
这样就把func3变成静态成员,它是绑定在类上面的,对于不同的对象,只有一个拷贝,因此编译器可以确定它的函数指针。但是随之而来的麻烦就是要把它调用到的所有成员(函数和变量)都声明为static类型。这样一来就使所有的对象都可以共享成员变量,使数据变得不安全。另外,如果要传递的函数是重载的虚函数,那么将会报错。因此这种方法具有局限性。
(3)把要传递的函数声明为friend类型,作为友元函数访问类中的成员。友元函数不属于该类,因此可以直接传递给外部的函数,但是同方法(2)一样,需要把所有它调用的成员也声明为static类型,给数据带来不安全。
(4)上面的方法都不太方便。最好的办法是用一个友元(或者全局)函数把要传递的成员函数封装一层,将这个友元函数的函数指针传递给外部的普通函数,而在友元函数内调用该成员函数。这样既不用破坏其他成员函数和变量的属性,保持了类原来的形式,也达到了传递类成员函数指针的目的。实际应用中,回调函数的参数表中一般都含有void*data,这是外部函数留给用户的一个数据接口,因此我们也可以利用这个数据接口将对象的this指针传进友元函数,用this指针调用要传递的类成员函数。程序如下:

#include <iostream>
using namespace std;

// 外部的普通函数,接受一个函数指针和一个void指针作为参数
void mfun(void (*pfun)(void *data), void *data)
{
(*pfun)(data);
}

class test
{
public:
friend void passfun(void *data); //声明一个友元函数

void func1()
{
mfun(passfun, this);//把友元函数的指针和this指针传递给外部函数
}

private:
void func2(void *data)
{
cout<<"testfunc2."<<endl;
}
};

void passfun(void *data)
{
((test*)data)->func2(data);//在友元函数中调用func2
}

main()
{
test my_test;
my_test.func1();
cin.get();
}

输出结果为:
test func2.

  

爱华网本文地址 » http://www.aihuau.com/a/25101017/338455.html

更多阅读

贾敏生前一再向林黛玉灌输贾府知识的玄机 林黛玉进贾府路线图

《红楼笔记》之七百九十五风之子原创近来几篇文章,引来几位挚友的争论,罪过。关于林黛玉初进贾府的相关情况,包括邢夫人,我还会有进一步分析,很多《红楼梦》的问题,都不是一两篇文章就能解决的,需要不断深入,不断感悟,不断分析,真相才会渐渐

EXCEL计算名次的问题两种方法if和rank函数 sql rank 函数

想借款想投资想理财上拍拍贷:http://www.ppdai.com/Register.aspx?userName=liumin2011EXCEL计算名次的问题2011-03-28 01:27在学校工作,要用EXCEL对学生的成绩进行名次计算。但是出现了一些问题,最后使用了比较麻烦的方法才把名次算出

C语言中scanf函数输入回车符的问题 c语言scanf连续输入

在用c语言编写输入语句的时候常用到scanf函数,初学者在刚用scanf函数输入时,经常会遇到各种各样的输入错误,最重要的是一定要记住scanf函数的输入格式,scanf函数里包含了哪些东西,输入的时候就必须有哪些东西,比如:scanf("%c%c%c"),那么输入

声明:《向普通函数传递类成员函数指针的问题 c 成员函数指针》为网友为爱成魔生执念分享!如侵犯到您的合法权益请联系我们删除