1:普通函数函数指针定义
我们知道 指向普通函数的指针,一般这么定义 :
数据类型名(*指针变量名)(参数列表)
void (*func)(int)
或者前面加一个 typedef
typedef 数据类型名(*指针变量名)(参数列表)
typedef void (*funv) (int)
这两种方式都可以,但是建议使用第二种方式:因为第二种方式相当于给 函数指针定义了一个别名,能隐藏笨拙的语法构造以及平台一些相关的数据类型,可以使得代码更美观,可维护性、可移植性、可读性更强。
实例:
如果不带 typedef 关键字
//定义一个函数void tech(void) { printf("tech dreamer"); }void main(){//定义一个指针,指针的名字叫func,它可以指向一个函数,并通过函数指针调用该函数void (*func)();func = &tech; // 将func()函数的入口地址赋给指针变量pf,所以,pf就指向func()函数func(); //第一种调用方式,带参数也可以(*func)();//第二种调用方式,带参数也可以}
增加 typedef 关键字
void tech(void) { printf("tech dreamer"); }//命名一个类型,那么这个时候func不可以直接调用,而是一个类型了typedef void (*func)();void main(){//定义一个可调用的指针变量(函数):myfunc (这个是主要区别)func myfunc;myfunc = &tech; //将func()函数的入口地址赋给指针变量pf,所以,pf就指向func()函数myfunc(); //第一种调用方式,带参数也可以(*myfunc)();//第二种调用方式,带参数也可以}
2:对象成员函数函数指针定义
标题1介绍了,普通函数函数指针的定义,对象成员函数指针定义情况相比要复杂一些。 那么复杂在哪里了?
首先成员函数和普通函数的根本区别是:成员函数是类中的一个成员,编译系统要求在指针赋值语句中,指针变量的类型必须与赋值右侧函数的类型相匹配,具体以下三个方面需匹配。
函数参数的类型和参数的个数要匹配函数返回值要匹配函数所属的类要匹配
所以定义指向公用的 成员函数的指针变量操作步骤为:
1:定义形式:数据类型名 (类名:: *指针变量名)(参数列表)
2: 函数指针赋值: 指针变量名 = &类名::成员函数名
可以让它指向一个公用成员函数,只需要把公用成员函数的入口地址赋值给一个指向公用成员函数的指针变量即可。
3:函数调用:(对象名.*函数指针变量名)()
思考:这样定义的函数指针变量,指向了一个类中的一个函数。但是,当一个类实例化为多个对象的时候,到底要怎样使用该函数指针?函数指针指向哪一个对象函数,所以,我们在调用函数指针的时候,就必须指定哪一个对象。看下面这个例子:
// main.cpp#include<iostream>#include<string>class Student{public:// 定义成员变量char name[32];char addr[32];long number;Student(char* pn, char* pa, long n) {strcpy_s(name, pn);strcpy_s(addr, pa);number = n;}void print() {std::cout << "name = " << name << std::endl;std::cout << "addr = " << addr << std::endl;std::cout << "number = " << number << std::endl;}private:};// 定义Student类中的一个函数指针void(Student::* pFunc)();int main(void) {std::string name = "xiaoming";std::string addr = "wuhan";Student stu((char*)name.c_str(),(char*)addr.c_str(), 123456789);// 给函数指针赋值pFunc = &Student::print;// 通过函数指针调用成员函数(且必须指定具体类对象)(stu.*pFunc)();return 0;}// 打印结果name = xiaomingaddr = wuhannumber = 123456789
这里有个知识点:大家可以好好体会。
对象的成员函数不是存放在对象的空间中的,而是存放在对象外的空间中。如果有多个同类的对象,他们公用同一个函数代码段(类的成员函数),那么他们不是属于某一个对象,而是属于该类,由所有的类对象共享。因此,Student类中的 print()成员函数,不是属于stu对象的,而是属于 Student类。所以,给指针变量 pFunc赋值的地址,应该是Student类公用的函数代码段的入口地址。