C++函数指针

发布于:2025-07-15 ⋅ 阅读:(14) ⋅ 点赞:(0)

函数指针的调用:

调用函数的两种方式:

  • 直接调用:通过函数名(函数的入口地址)直接调用
  • 间接调用:通过函数指针指向函数间接调用
void(*p_fun)(int)=&fun; //定义变量并初始化
p_fun = &fun; //赋值,指向一个函数
(*p_fun)(10); //间接调用函数
#include <iostream>
using namespace std;

// 定义一个函数,接受一个整数参数并打印
void show(int a) {
    cout << "show(int)" << " " << a << endl;
}

// 定义一个函数,接受一个函数指针作为参数
void fun_show(void (*p_fun)(int)) {
    (*p_fun)(30); // 通过函数指针调用传入的函数
}

int main() {
    show(10); // 直接调用 show 函数,输出: show(int) 10

    // 定义一个函数指针并初始化,使其指向 show 函数
    void (*p_fun)(int) = &show; 
	//定义函数指针且初始化,可以不加取地址符号,因为函数名就是函数地址
    (*p_fun)(20); // 可以用这行代码间接调用 show 函数,输出: show(int) 20
    
    // 直接调用函数指针 p_fun
    p_fun(20); // 使用函数指针 p_fun 调用 show 函数,输出: show(int) 20

    // 将函数指针 p_fun 赋值为 show 函数(可以省略取址符号 &)
    p_fun = &show; // 赋值(&show 是可选的)
    
    // 调用 fun_show,并将函数指针 p_fun 作为参数传递
    fun_show(p_fun); // 输出: show(int) 30

    return 0;
}

函数指针有时看起来比较繁琐、可读性差一些,我们可以用typedef进行优化 

typedef void(*P_FUN)(int);
P_FUN p_fun = &fun;
//将函数指针用typedef进行优化
#include <iostream>
using namespace std;

// 定义一个接受一个整数参数并打印的函数
void show(int a) {
    cout << "show(int)" << " " << a << endl;
}

// 使用 typedef 优化函数指针的定义
typedef void (*P_FUN)(int);

// 定义一个函数,接受一个函数指针作为参数
void fun_show(P_FUN p_fun) {
    (*p_fun)(30); // 通过函数指针调用传入的函数,并传入 30
}

int main() {
    P_FUN p_fun = &show; // 使用 typedef 定义的函数指针并指向 show 函数
    fun_show(p_fun); // 调用 fun_show,并传入 p_fun
    return 0;
}

使用函数指针调用函数的好处:

函数指针可以实现同一功能的多个模板统一标识起来,是系统结构清晰,后期更容易维护,便于分层设计,利于系统抽象,降低耦合,使接口与实现分离,提高代码的复用性,扩展性

嵌套函数指针:

#include <iostream>
using namespace std;

/*
func :函数名 挨着函数名的第一个括号里是参数
参数列表:(char*, void(*)(bool, double*)) ,两个参数,参数1:char*
参数2:void(*)(bool, double*)
返回值:void (*)(int*, void* (char, bool*)),返回值是函数指针,指向的函
数:void (int*, void* (char, bool*))
*/

// 定义函数指针类型
typedef void(*P_PARAM)(bool, double*); // P_PARAM 指向接受 bool 和 double* 的函数
typedef void* F_PARAM(char, bool*); // F_PARAM 指向接受 char 和 bool* 的函数并返回 void*
typedef void (*P_RET)(int*, F_PARAM f); // P_RET 指向接受 int* 和 F_PARAM 的函数

// func 函数定义,接受 char* 和一个函数指针
void (*func(char*, void(*)(bool, double*)))(int*, void* (char, bool*)) {
    cout << "优化前函数" << endl;
    return nullptr; // 返回值应为 nullptr,表示没有返回有效指针
}

// func1 函数定义,接受 char* 和 P_PARAM 类型函数指针
P_RET func1(char*, P_PARAM p1) {
    cout << "优化后函数" << endl;
    return nullptr; // 返回值应为 nullptr,表示没有返回有效指针
}

int main() {
    char* p = new char[1](); // 动态分配一个字符数组
    P_PARAM p11 = nullptr; // 初始化函数指针 p11 为 nullptr
    P_RET pRet = func(p, p11); // 调用 func 函数
    pRet = func1(p, p11); // 调用 func1 函数
    delete[] p; // 释放之前分配的内存
    return 0;
}

类成员函数指针:

 类成员函数与普通的函数的区别:

  1. 所属的作用域不同,类成员函数标识了所属的类,必须通过对象调用(虽然可以是空指针对象,但必须得有)。
  2. 类成员函数编译器会默认加上一个隐藏的参数: this指针。所以定义类成员函数的指针与普通的函数指针肯定会有所区别:C++ 提供了三种运算符 ::* 、.*、 ->. 用于定义和使用类成员函数指针。
  3. 类成员函数指针的&取地址符号不可省略,而普通函数的可以。
::* :定义类成员函数指针
.* :用对象通过类成员函数指针调用指向的函数
->* :用指针对象通过类成员函数指针调用指向的函数
注:
类成员函数指针的定义一定是 void (CTest ::* p_fun)(int a) = &CTest::show;
而不是 void (CTest ::(*p_fun)(int a) = &CTest::show;

类成员函数定义与调用:

#include <iostream>
using namespace std;
class CTest {
	public:
		void show(/* CTest * const this */int a) {
			cout << this << endl; //输出tst的地址
			cout << "CFather::show" << a << endl;
		}
};
int main() {

	void (CTest::*p_fun)(int a) = &CTest::show;
//定义类成员函数指针并初始化,注意:& 和类名作用域 都不能省略,

//优化
	typedef void (CTest::*P_FUN)(); //使用typedef 进行优化
	P_FUN p_fun2 = &CTest::show;

//定义
	CTest tst;
	CTest*pTst = new CTest;
	CTest* pTst = &tst;

//调用
	(pTst->*p_fun)(20);
	(tst.*p_fun2)(); //普通对象通过指针调用类成员函数
	(pTst->*p_fun2)(); //指针对象通过指针调用类成员函数

}

仿写多态:

可以用类成员函数指针来模拟实现多态。用父类指针调用子类函数

 

#include <iostream>
using namespace std;
class CPeople {
	public:
		int m_money;
		CPeople() {
			m_money = 10;
		}
		void cost(int n) {
			m_money -= n;
		}
		void show() {
			cout << "m_money:" << m_money << endl;
		}
};
class CYellow :public CPeople {
	public:
		void eat() {
			cout << "用筷子夹菜吃饭" << endl;
		}
};
class CWhite :public CPeople {
	public:
		void eat() {
			cout << "用刀叉吃肉" << endl;
		}
};
class CBlack :public CPeople {
	public:
		void eat() {
			cout << "用手抓饭" << endl;
		}
};
typedef void(CPeople::* P_FUN)();
void fun(CPeople* p, P_FUN p_fun) {
    p->cost(1);
    p->show();
    (p->*p_fun)(); // 调用成员函数
}
	//CPeople* p,这是一个指向 CPeople 类对象的指针。
	//由于 CPeople 是一个基类,p 可以指向任何 
	//CPeople 的派生类对象(例如 CYellow、CWhite、CBlack),
	//这体现了多态性的特性。
	
	//P_FUN p_fun,这是一个指向 CPeople 类成员函数的指针。
	//P_FUN 是之前定义的类型别名,表示返回类型为 void,
	//且没有参数的成员函数指针。通过传递这个指针,
	//可以在 fun 函数内部调用特定的成员函数。

int main() {
	CPeople* pPeo = new CYellow;
	typedef void(CPeople::* P_FUN)();
//void(CPeople:: * p_fun)() = (void(CPeople::*)())&CYellow::eat;
    P_FUN p_fun = (P_FUN)&CYellow::eat; // 获取 CYellow::eat 的指针
//通过强转指向子类的函数
    (pPeo->*p_fun)(); // 调用 eat 方法
    fun(new CWhite, (P_FUN)&CWhite::eat); // 调用 CWhite 的 eat 方法
    fun(new CBlack, (P_FUN)&CBlack::eat); // 调用 CBlack 的 eat 方法
    return 0;
}


网站公告

今日签到

点亮在社区的每一天
去签到