C++函数指针

指针是表示内存中(虚拟)地址的标识符

对于一个函数,它的函数名就代表了这段代码的地址

复制代码
double multiplay(double a,double b)
{
	return a*b;
}

cout<<hex<<(unsigned long long) multiplay<<endl;  //输出:40157f

定义函数指针

采用如下方式定义函数指针:

复制代码
返回类型 (*函数指针名)(参数列表)

不能把包裹 *函数指针名的括号拿掉,不然就变成了定义指针函数的语法

定义函数与定义函数指针

为了方便方便记忆,我们来看看定义函数和定义函数指针的有哪些联系:

复制代码
函数签名
double multiplay(double a,double b)

↓ 将函数名替换成 (*指针名),就完成了函数指针的定义
double (*ptr)(double a,double b)

↓ 由于参数名对指针没有意义,可以进一步去掉
double (*ptr)(double,double)
使用函数指针调用函数
复制代码
double multiplay(double a,double b)
{
	return a*b;
}
double add(double a,double b)
{
	return a+b;
}
//...
//函数指针指向函数,既可以直接赋予 函数名,也可以赋予 函数名+取地址运算符
double (*ptr1)(double,double) = multiplay;
double (*ptr2)(double,double) = &add;

//调用函数时,既可以用函数指针+参数的方式,也可以用括号+解引用运算符+函数指针+参数的方式
cout<<ptr1(4,5)<<endl;
cout<<(*ptr1)(4,5)<<endl;

//注意:此种写法相当于对函数返回值解引用,会导致错误
cout<< *ptr1(4,5) <<endl;   //相当于*(ptr1(4,5))
使用函数指针更改指向

在定义函数指针时,定义的是一个指针指向的函数的形式

因此对于返回值与参数相同的函数,可以使用这样的指针来指向

复制代码
double multiplay(double a,double b)
{
	return a*b;
}
double add(double a,double b)
{
	return a+b;
}
//...

double (*ptr)(double,double) = multiplay;
cout<< ptr(4,5)<<endl;       //输出:20
ptr = &add;
cout<< ptr(4,5)<<endl;       //输出:9
使用typedef给函数指针定义别名

前面的定义方式看起来比较繁琐,可以使用typedef定义类型别名进行简化

复制代码
//在定义函数指针的语法前加上typedef
//这时FuncPtr就不再是一个函数指针,而表示这种指针的类型
typedef double (*FuncPtr)(double,double)

//在后续使用时,就可以使用这个类型定义指针
FuncPtr ptr = multiplay;

//也可以用typedef定义一个没有指针的函数类型
typedef double (MyFuncType)(double,double)

//在后续使用时,使用指针的形式定义函数
MyFuncType* ptr = multiplay;
使用auto 自动类型推断
复制代码
double multiplay(double a,double b)
{
	return a*b;
}
double add(double a,double b)
{
	return a+b;
}
//...
typedef double (*FuncPtr)(double,double)

//可以使用auto自动推断出函数指针类型
auto ptr1 = multiplay;
cout<< ptr1(4,5) << endl;

//但auto不能推断函数指针数组
// auto ptrs[2] = {multiplay, add};  //错误
FuncPtr ptrs[2] = {multiplay, add};  //这时需要使用 函数指针类型 进行定义
cout<< ptrs[0](4,5) << endl;      
函数指针的使用

函数指针可以用作回调函数

复制代码
bool compare(float a,float b)
{
	return a<b;
}

int main()
{
	vector<float> numbers{0,1,3,0,0,4,9};
	sort(numbers.begin(),numbers.end(),compare);
	for(auto number:numbers) cout<< number <<" ";
	return 0;
}
题外话: 仿函数/函数对象

不过现在来说,更倾向于使用函数对象做回调

复制代码
class Compare
{
public:
	Compare(float a,float b) { }
	bool operator()(float a,float b)
	{
		return a<b;
	}
};

int main()
{
	vector<float> numbers{0,1,3,0,0,4,9};
	sort(numbers.begin(),numbers.end(),Compare());
	for(auto number:numbers) cout<< number <<" ";
	return 0;
}

补充一个易混点

复制代码
需要注意的是sort中的Compare()是创建一个对象,仿函数在sort内部调用
一般来说,使用类名()时 是在创建对象,使用对象名()时 是在调用仿函数
Compare comp;
Compare(1,2);       //创建一个临时对象
comp(1,2);          //调用函数
Compare(1,2)(1,2);  // 创建一个临时对象并调用函数

仿函数的最大优势在于,它可以有自己的状态

复制代码
class AddANum
{
public:
    int Num;
    int operator()(int x) const { return x + Num; }
};
类成员函数指针

类成员函数指针的定义方法:

复制代码
返回类型 (类名::*函数指针名称)(参数列表);

class Calc
{
	public:
	double multiplay(double a,double b){ return a * b; }
	double add(double a,double b){ return a + b; }
};
int main()
{
	//给类成员函数指针赋值时前面建议加上& 不加&有的编译器会报错
	double (Calc::*PtrMemberFunc)(double,double) = &Calc::multiplay;

	//如下演示了使用对象和指针调用函数,语法要一致 括号的位置要一致、*号也不能丢 
	Calc c1;
	cout<<(c1.*PtrMemberFunc)(4,5)<<endl;    //结果:20
	
	PtrMemberFunc = &Calc::add; 
	Calc* c2 = &c1;
	cout<<(c2->*PtrMemberFunc)(4,5)<<endl;   //结果:9
	
	return 0;
}
类成员函数指针仍然具有多态性
复制代码
class BaseClass
{
public:
	virtual void print(){ cout<<"Base class"<<endl;	}
};

class SubClass :public BaseClass
{
public:
	virtual void print() override { cout<<"Sub class"<<endl;	}
};

int main()
{
	void (BaseClass::*pMenFunc)() = &BaseClass::print;
	
	BaseClass* obj = new SubClass();
	(obj->*pMenFunc)();              //输出:Sub class
}
相关推荐
皓月斯语1 小时前
B2132 素数对
c++·算法·题解
星轨初途2 小时前
LeetCode 热题 100——day2 字母异位词分组
c++·算法·leetcode
笨鸟先飞的橘猫2 小时前
c++面向对象编程
开发语言·c++
啦啦啦啦啦zzzz3 小时前
设计模式:桥接模式和组合模式
c++·设计模式·组合模式·桥接模式
-森屿安年-3 小时前
647. 回文子串
c++·算法·动态规划
fpcc3 小时前
c++应用网络编程之十七WebSocket
网络·c++·websocket
haolin123.3 小时前
类和对象(下)
c语言·开发语言·c++
皓月斯语3 小时前
P5736 【深基7.例2】质数筛
c++·算法·题解
鸿芯微控科技4 小时前
MFC质量流量控制器流量不准怎么排查?设定值、反馈值与参考流量对比,附Python代码
c++·python·mfc
拂拉氏4 小时前
【知识讲解】 让指针拥有“自我意识”?--C++智能指针相关内容讲解
c++·智能指针