// C++Test.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #include <string> #include <list> using namespace std; //定义一个函数指针 void (*pFunc)(int); //声明并定义一个函数 void PrintInt(int i) { cout<<i<<endl; } int _tmain(int argc, _TCHAR* argv[]) { //将函数赋给函数指针 //不使用&符号也可以,因为函数名称本来就是函数的首地址,类似数组 pFunc = &PrintInt; //通过函数指针来调用函数 pFunc(1); //调用时也可以写的完整规范一些(*pFunc)(1)符合一般指针的标准 system("pause"); return 0; }结果:
// C++Test.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #include <string> #include <list> using namespace std; //使用typedef定义函数指针,此时,pFunc就不再是函数指针本身的名称,而是这类函数指针的一个别名 typedef void (*pFunc)(int); //声明并定义一个函数 void PrintInt(int i) { cout<<i<<endl; } int _tmain(int argc, _TCHAR* argv[]) { //定义一个函数指针,并赋予其初始值 pFunc func = PrintInt; //通过函数指针来调用函数 func(1); system("pause"); return 0; }结果:
成员函数指针是C++中最麻烦的东东之一,准确的说是非静态成员函数指针。
静态成员函数指针与普通函数指针一样,我们看一个例子:
// C++Test.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #include <string> #include <list> using namespace std; //Base类 class Base { public: static void Print(int num) { cout<<num<<endl; } }; //定义一个静态成员函数指针 typedef void (*pFunc)(int); int _tmain(int argc, _TCHAR* argv[]) { //将静态成员函数赋给函数指针 pFunc func = Base::Print; //通过函数指针调用函数 func(1); system("pause"); return 0; }
结果:
1
请按任意键继续. . .
静态成员函数与普通的函数没有太多区别,虽然他们定义在类中,但是这个成员函数不会因为对象的不同而做出不同的处理,因为它没有this指针,所以我们可以将它看成普通的函数。
但是非静态成员函指针就麻烦得多,原因非静态成员函数有一个隐藏的参数--this指针,这个东东在不同的对象中是不一样的,所以很麻烦。我们定义非静态成员函数指针的时候就需要将对象的类型也写出来。调用的时候,也要根据相应的对象来调用这个函数。看一个例子:
// C++Test.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #include <string> #include <list> using namespace std; //Base类 class Base { public: void Print(int num) { cout<<num<<endl; } }; //定义一个成员函数指针 typedef void (Base::*pFunc)(int); int _tmain(int argc, _TCHAR* argv[]) { Base base; //取成员函数的地址,必须以这种形式,不能以对象的形式获取,而且必须加上&符号 pFunc func = &Base::Print; //调用的时候写法也比较特殊,base.*func表示函数体,是一个整体,需要用() (base.*func)(1); system("pause"); return 0; }结果:
1
请按任意键继续. . .
分析一下成员函数指针的定义和使用,我们这样定义函数指针,(Base::*pFunc)(int),其实就相当于(*pFunc)(Base*, int),相当于普通的函数指针需要多一个this指针作为参数,而这个this指针在不同的对象中一定是不同的,所以成员函数指针之间是不能互相转化的,只有同类型的对象的函数才能赋给这种对象的函数指针。
在指针赋值的时候,注意一下写法,普通的函数指针在赋值的时候,可以不写&符号,但是成员函数指针赋值的时候比较严格,如果不写的话会报出这样的错误:
error C3867: “Base::Print”: 函数调用缺少参数列表;请使用“&Base::Print”创建指向成员的指针
而且在赋值的时候,不要用对象赋值,要用 类名::函数名 这种方式赋值,使用 对象名.函数名的时候会报出这样的错误:
error C2276: “&”: 绑定成员函数表达式上的非法操作
可见,对于成员函数指针的写法还是挺严苛的。
最后再分析一下使用,由于成员函数指针需要一个this指针作为参数,这个参数又不能直接给出,所以我们就只能通过对象来调用函数,在使用函数的时候,由于函数是一个整体,所以需要用(),在括号内部,我们通过*func获得函数,然后前面使用base.就将base作为this指针传递给了函数。
那么,既然这个函数是非静态成员函数,那么这个函数支不支持动态绑定呢?换句话说就是,我们声明的函数指针是基类的函数指针,子类覆写了这个函数,那么,用子类对象调用的时候,是调用基类的函数还是子类的函数呢?我们看一个例子:
// C++Test.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #include <string> #include <list> using namespace std; //Base类 class Base { public: //虚函数 virtual void Print(int num) { cout<<"base: "<<num<<endl; } }; class Child : public Base { public: //覆写基类的Print方法 void Print(int num) override { cout<<"child: "<<num<<endl; } }; //定义一个成员函数指针 typedef void (Base::*pFunc)(int); int _tmain(int argc, _TCHAR* argv[]) { Base base; Child child; //给函数指针赋值的时候,必须是用声明函数指针的类来赋值(此处为Base) pFunc func = &(Base::Print); //通过base对象调用函数指针 (base.*func)(1); //通过child对象调用函数指针 (child.*func)(1); //查看函数指针的大小 cout<<"sizeof Member Function: "<<sizeof(func)<<endl; system("pause"); return 0; }结果:
base: 1
child: 1
sizeof Member Function: 4
请按任意键继续. . .
从上面的结果,我们看出,在最后使用函数指针的时候,这个this指针的对象可以是我们声明函数指针的时候的对象的子类,并且如果我们覆写了基类的函数,是可以调用子类的函数的(注意是覆写基类的virtual函数,如果只是单纯的覆盖是没有多态效果的)。
我们分析一下原因,还是这样看待这个函数指针,把它看成普通函数指针增加了一个类对象的this指针作为参数,这个形参我们可以声明为基类的指针,我们给实参的时候,可以给基类的对象,当然也可以给子类对象,这就跟我们普通函数传递参数的情况一样,然后这个参数传递进去,如果有virtual函数,那么就可以触发多态。但是我们在给函数指针赋值的时候,却只能使用基类的函数,因为我们没有声明子类的函数。
// C++Test.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #include <string> #include <list> using namespace std; //定义pcall这种函数指针的类型 typedef int (*pcall)(int, int); //处理函数,接受一个pcall类型的函数作为参数 void Func(pcall p, int x, int y) { cout<<"begin func:"<<endl; cout<<"result is : "<<p(x, y)<<endl; cout<<"end func"<<endl; } //加法函数 int AddFunc(int x, int y) { return x + y; } //减法函数 int SubFunc(int x, int y) { return x - y; } int _tmain(int argc, _TCHAR* argv[]) { //将函数指针作为参数传递给函数 //&符号可以省略 Func(&AddFunc, 2, 1); Func(&SubFunc, 2, 1); system("pause"); return 0; }结果:
// C++Test.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #include <string> #include <list> using namespace std; class Baker { private: int m_iTime; //做蛋糕的时间 static const int m_iMaxTime = 10;//假设10分钟做完 public: //做蛋糕,如果做好了返回true,否则返回false bool MakeCake(); //构造函数 Baker(); }; Baker::Baker() : m_iTime(0){} bool Baker::MakeCake() { //假设每次调用该函数,m_iTime+1 m_iTime += 1; if (m_iTime == m_iMaxTime) { cout<<"蛋糕做好了!"<<endl; return true; } return false; } //客户函数 void GetMyCake() { cout<<"我来取蛋糕啦!"<<endl; } int _tmain(int argc, _TCHAR* argv[]) { //创建一个蛋糕店 Baker baker; //做蛋糕 while(1) { //客户如果想第一时间知道蛋糕做没做好,就必须每时每刻查看蛋糕的情况 if (baker.MakeCake()) { GetMyCake(); break; } else cout<<"蛋糕没做好"<<endl; } system("pause"); return 0; }结果:
// C++Test.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #include <string> #include <list> using namespace std; //声明一种回调函数 typedef void (*CallBackFunc)(void); class Baker { private: int m_iTime; //做蛋糕的时间 static const int m_iMaxTime = 10;//假设10分钟做完 CallBackFunc m_pfCallBack;//回调函数 public: //注册:留下买蛋糕的人的联系方式 void Invoke(CallBackFunc); //打电话通知买蛋糕的人 void Notify(); //做蛋糕,如果做好了,直接通知客户 void MakeCake(); //构造函数 Baker(); }; Baker::Baker() : m_iTime(0){} void Baker::MakeCake() { while(m_iTime < m_iMaxTime) { //假设每次调用该函数,m_iTime+1 m_iTime += 1; } cout<<"蛋糕做好了!"<<endl; Notify(); } void Baker::Invoke(CallBackFunc pfunc) { //注册过程 m_pfCallBack = pfunc; cout<<"留下了您的联系方式!"<<endl; } void Baker::Notify() { if (m_pfCallBack) m_pfCallBack(); } //客户函数 void GetMyCake() { cout<<"我来取蛋糕啦!"<<endl; } int _tmain(int argc, _TCHAR* argv[]) { //创建一个蛋糕店 Baker baker; //注册:留下联系方式 baker.Invoke(GetMyCake); //注册之后,客户就不需要实时查询了 cout<<"好了叫我就好,我去玩儿啦!"<<endl; //做蛋糕 baker.MakeCake(); system("pause"); return 0; }结果:
//定义一个函数指针 typedef int (*pFunc)(void); //定义一个指针函数 int* PointerFunc(void) { int a = 1; return &a; }函数指针*和名字是放在一起的,而指针函数*是和返回值放在一起的。
//定义一个指针函数的函数指针 typedef int* (*pFUN)(void);
参考链接:http://blog.chinaunix.net/uid-10386087-id-2959230.html
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文:http://blog.csdn.net/puppet_master/article/details/49368863