飞道的博客

c++函数指针相关知识点详细总结!!!

402人阅读  评论(0)

函数指针初识

  • 函数指针指向的是函数而非对象。
  • 和其他指针一样,函数指针指向某种特定类型。
  • 函数的类型由它的返回类型和形参类型共同决定。
  • 例如:
//比较两个string对象的长度
bool lengthCompare(const string& s1,const string& s2);
  • 该函数的类型是
  • bool(const string&,const string&).
  • 要想声明一个可以指向该函数的指针,只需要用指针替换函数名即可:
	//pf指向一个函数,该函数的两个参数是const string的引用,返回值是bool类型
	bool (*pf)(const string & , const string &);//未初始化

注意:pf两端的括号比不可少,如果不写,则pf是一个返回类型为bool指针的函数

函数指针的使用

  • 当我们把函数名作为一个值使用时,该函数自动转换为指针。
	pf = lengthCompare;//pf指向名为lengthCompare的函数
	pf=&lengthCompare; //等价赋值语句:取地址符是可逆的
  • 此外,我们还能直接使用指向函数的指针调用该函数,无须提前解引用指针:
	bool b1 = pf("hello", "goodbye");//调用lengthCompare函数
	bool b2 = (*pf)("hello", "goodbye");//一个等价的调用
	bool b3 = lengthCompare("hello", "goodbye");//另一个等价调用
  • 在指向不同函数类型的指针间不存在转换规则
  • 我们可以将函数指针赋值为nullptr或者值为0的整形常量表达式,表示当前函数指针没有指向任何一个函数
bool lengthCompare(const string& s1, const string& s2)
{
   
	cout <<s1<<" "<<s2<< endl;
	return true;
}
string::size_type sumLength(const string&, const string&)
{
   
	return 0;
}
bool cstringCompare(const char*, const char*)
{
   
	return true;
}
	pf = 0;//正确:pf不指向任何函数
	pf = sumLength;//错误:返回类型不匹配
	pf = cstringCompare;//错误:形参类型不匹配
	pf = lengthCompare;//正确:函数和指针类型精确匹配

重载函数指针

  • 当我们使用重载函数时,上下文必须精确地界定到底应该选用哪个函数。
void ff(int*)
{
   
	cout << "ff(int*)" << endl;
 }
void ff(unsigned int)
{
   
	cout << "ff unsigned int" << endl;
}
void test()
{
   
	void (*pf1)(unsigned int) = ff;//pf1指向ff(unsigned)
	pf1(1);
}

  • 编译器通过指针类型决定选用哪个函数,指针类型必须与重载函数中某一个精确匹配。
	void (*pf2)(int) = ff;//错误:没有任何一个ff与该形参列表匹配
	int (*pt3)(int*) = ff;//错误:没有任何一个ff与pt3的返回类型匹配

函数指针形参

  • 虽然不能定义函数类型的形参,但是形参可以是指向函数的指针。此时形参看起来是函数类型,实际上却是当做指针使用。
//比较两个string对象的长度
bool lengthCompare(const string& s1, const string& s2)
{
   
	if(s1.size()>s2.size())
	return true;
	return false;
}
//第三个参数是函数类型,它会自动转换成指向函数的指针
bool useBigger(const string& s1, const string& s2, bool bf(const string& s1, const string& s2))
{
   
	return bf(s1, s2);
}
void test()
{
   
	string s1 = "abc";
	string s2 = "abcdfe";
	if (useBigger(s1, s2, lengthCompare))
	{
   
		cout << "s1大于s2" << endl;
	}
	else
		cout << "s1小于s2" << endl;
}
//等价的声明:显示地将形参定义成指向函数的指针
bool useBigger(const string& s1, const string& s2, bool (*bf)(const string& s1, const string& s2))
{
   
	return bf(s1, s2);
}
  • 我们可以直接把函数作为实参使用,此时它会自动转换为指针
//自动将函数lengthCompare转换成指向该函数的指针
useBigger(s1, s2, lengthCompare);
//或者也可以用取地址符
useBigger(s1, s2, &lengthCompare);

  • 类型别名和decltype能让我们简化使用了函数指针的代码:
     //func和func2是函数类型
	typedef bool func(const string&, const string&);
	typedef decltype(lengthCompare) func2;//等价的类型
	//funcp和funcp2是指向函数的指针
	typedef bool(*funcp)(const string&, const string&);
	typedef decltype(lengthCompare)* funcp2;//等价的类型
  • 我们使用typefdef定义自己的类型,func和func2是函数类型,而funcp和funcp2是指针类型,需要注意的是decltype返回函数类型,此时不会将函数类型自动转换为指针类型因为decltype的结果是函数类型,所以只有在结果前面加上*才能得到指针。
  • 可以使用如下形式重新声明useBigger:
	//useBigger的等价声明,其中使用了类型别名
	void useBigger(const string & s1, const string & s2, func);
	void useBigger(const string & s1, const string & s2, func2);
	void useBigger(const string & s1, const string & s2, funcp);
	void useBigger(const string & s1, const string & s2, funcp2);
  • 前两句等价声明中,编译器自动把func表示的函数转换为指针

返回值指向函数的指针

  • 和数组类似,虽然不能返回一个函数,但是能返回指向函数类型的指针,
  • 然而,我们必须把返回类型写成指针形式,编译器不会自动地将函数返回类型当初对应的指针类型处理
  • 与前面一样,要想声明一个返回函数指针的函数,最简单的办法是使用类型别名:
using F = int(int*, int*);//F是函数类型,不是指针
using FF = int(*)(int*, int*);//FF是指针类型

注意:返回值不会自动地转换为指针,我们必须显示将返回类型指定为指针

	FF f1(int);//正确:FF是指向函数的指针,f1返回指向函数的指针
	F f2(int);//错误:F是函数类型,f1不能返回一个函数
	F* f3(int);//正确:显示地指定返回类型是指向函数的指针
  • 当然,我们也可以用下面形式直接声明f1:
	int (*f1(int))(int*, int*);
  • 按照由内向外的顺序阅读这条声明语句:我们看到f1有形参列表,所以f1是个函数;

  • f1前有*,所以f1返回一个指针;

  • 进一步观察发现,指针的类型本身也包含形参列表,因此指针指向函数,该函数返回的类型是int.

  • 举例说明:

int addSum(int* a, int* b)
{
   
	cout << "a+b= " << *a + *b << endl;
	return 1;
}
int (*f1(int val))(int*, int*)
{
   
	 addSum(&val, &val);
	 return addSum;
}
void test()
{
   
	auto ret = f1(10);
}

将auto和decltype用于函数指针类型

  • 如果我们明确知道返回的函数是哪一个,就能使用decltype简化书写函数指针返回类型的过程。
string::size_type a(const string& s1, const string& s2)
{
   
	return s1.size() + s1.size();
}
string::size_type b(const string& s1)
{
   
	return s1.size() + s1.size();
}
decltype(a) * getFunc(const string& s)
{
   
	cout << "a(s,s)= " << a(s, s) << endl;
	b(s);
	return a;
}
void test()
{
   
	auto ret = getFunc("abc");
	cout << ret("abcd","casd") << endl;
	//直接打印函数名,或解引用的效果一样,得到的都是函数的地址
	cout << ret<< endl;
	cout << *ret<< endl;
}


点个赞,再走吧,个位亲


转载:https://blog.csdn.net/m0_53157173/article/details/116266434
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场