类成员函数指针

类成员函数指针

普通成员函数

类被需要的时候会被载入内存,当然类成员函数也会被载入内存,所以类的成员函数是有真正的内存地址的,这个地址一般跟具体的类对象没有什么关系
类成员函数指针,通俗的讲,是一个指针,指向类成员函数
使用方法如下
示例

#include <iostream>
#include <string.h>
using namespace std;


class CT
{
public:
	void func(int tmp)
	{
		cout << "func()普通函数,   tmp = " << tmp << endl;
	}
	virtual void virtualfunc(int tmp)
	{
		cout << "virtualfunc()虚函数,   tmp = " << tmp << endl;
	}
	static void staticfunc(int tmp)
	{
		cout << "staticfunc()静态成员函数,   tmp = " << tmp << endl;
	}
};

int main(void)
{
	CT ct;
	CT* pct;
	pct = &ct;

	void(CT:: * func_pointpt)(int);  //一个类成员函数指针变量的定义, 变量名为func_pointpt
	func_pointpt = &CT::func;

	(ct.*func_pointpt)(100);     //运算符优先级,这里要加括号
	(pct->*func_pointpt)(100);

	//类成员函数指针,必须定义类来调用.
	return 0;
}

在这里插入图片描述

虚成员函数

上述案例中已经有写虚函数的接口,这里可以调用
虚成员函数与普通成员函数是一样的写法

main中

    CT ct;
	CT* pct;
	pct = &ct;

	void(CT:: * func_pointpt)(int) = &CT::virtualfunc;

	(ct.*func_pointpt)(100); 
	(pct->*func_pointpt)(100);

请注意,这个地址其实也是一个真正的内存地址,类中一旦有虚函数,就会自动产生一个虚函数表,希函数表里有许多表项,每个表项是一个指针,每个指针指向一个虚函数地址.
用法同样也是要把指针绑定到一个类对象才能调用

静态成员函数

因为静态成员函数是跟着类走的,与具体的对象无关,这表示静态成员函数被看作全局函数,因此并没有用"类名::"这种作用域限定符来限定

	void(* func_pointpt)(int) = &CT::staticfunc;
    func_pointpt(100);
<think>首先,用户的问题是关于“C++类成员函数指针使用方法示例”。回顾之前的对话历史:-用户最初问的是关于“类名访问静态成员变量”,我详细解释了声明、初始化、访问方法、注意事项和示例。-现在,用户说:“参考站内引用:”,并提供了几个引用,涉及类成员函数指针的应用和示例:-引用[1]:展示了声明类成员函数指针的示例。-引用[2]:讨论了C++类成员函数指针的使用区别。-引用[3]:展示了指向静态成员函数的指针使用,指出它与普通函数指针类似。-引用[4]:讨论了如何将类的非静态成员函数用作回调函数。-用户明确表示:“我想了解类成员函数指针的用法或解决相关问题”。系统指令:-使用LaTeX:行内用`$...$`,独立公式用`$$...$$`。-中文回答。-生成相关问题。-引用段落末尾自然地添加引用标识,例如[^1]。-回答结构清晰,逐步解决问题,保证真实可靠。-在末尾添加相关问题。从引用中提取关键点:-类成员函数指针用于指向类的成员函数。-非静态成员函数指针需要额外的对象实例来调用。-静态成员函数指针可以像普通函数指针一样使用。-有陷阱,如"referencetonon-staticmemberfunctionmustbecalled"错误。我的回答需要:1.**结构清晰**:逐步解释使用方法。2.**提供示例**:包括代码示例。3.**区分静态和非静态**:因为引用[3]强调了区别。4.**添加引用**:自然地引用相关段落,基于用户提供的引用。5.**生成相关问题**:在回答末尾。大纲:-**引言**:简要介绍类成员函数指针。-**声明和初始化**:解释如何声明类成员函数指针,包括语法。-**使用示例**:提供代码示例:-非静态成员函数的指针使用。-静态成员函数的指针使用(因为它更简单)。-如何使用回调函数的示例(基于引用[4])。-**注意事项**:比如调用非静态成员函数指针时需要一个对象实例。-**结论**:总结关键点。-**相关问题**:生成2-3个相关问题。确保使用LaTeX:-在需要处添加数学表达式,但由于主题与数学无关,可能只用于强调变量或函数名。-例如,解释指针类型时,可以用`$type(*ptr)(params)$`。参考用户提供的引用:-在回答中,自然地插入引用标识。-例如,在解释时引用[^1],[^2],[^3],[^4]。具体步骤:1.**介绍类成员函数指针**:解释它用于指向类的成员函数。2.**语法声明**:使用用户引用[1]的代码作为基础。-示例:`void(MyClass::*ptr)(int)=&MyClass::MyFunction;`3.**非静态成员函数指针**:-调用时需要对象实例。-示例代码展示。4.**静态成员函数指针**:它像普通函数指针。-基于引用[3]的代码。5.**回调函数应用**:讨论如何用于回调(来自引用[4])。6.**注意事项**:-编译错误"referencetonon-staticmemberfunctionmustbecalled"(引用[2])。-确保权限控制(私有成员)。7.**代码示例**:用代码块展示。-使用C++代码。8.**生成相关问题**:-例如:"如何避免类成员函数指针的常见错误?"、"静态vs非静态成员函数指针的区别?"、"在实际项目中如何使用类成员函数指针?"完整响应结构:-**标题**:C++类成员函数指针的使用方法及示例-**正文**:分步骤解释。-**代码示例**:用Markdown代码块。-**注意事项**:列出关键点。-**相关问题**:在结尾。保持中文回答。</think> ### C++ 类成员函数指针的使用方法及示例 类成员函数指针C++中用于指向类成员函数的指针类型。它分为**非静态成员函数指针**和**静态成员函数指针**,用法略有不同。以下我将逐步解释其使用方法、提供代码示例,并讨论注意事项。本内容基于C++标准,参考您提供的引用材料[^1][^2][^3][^4]。 --- ### 🔑 1. 声明和初始化类成员函数指针C++中,声明类成员函数指针需要使用特定语法:`ReturnType (ClassName::*ptr)(Params)`,其中 `ptr` 是指针名, `ReturnType` 是函数返回类型, `Params` 是函数参数表。这与普通函数指针不同,因为它需要类名限定作用域。 - **非静态成员函数指针**:需要绑定到对象实例上调用。声明时指定类名,如 `void (MyClass::*ptr)(int)`。 - **静态成员函数指针**:与普通函数指针类似,因为静态成员函数不依赖对象实例。声明时为 `ReturnType (*ptr)(Params)`,不需要类名限定。 参考引用[^1]的代码: ```cpp class MyClass { public: void MyFunction(int x) { /* 非静态成员函数 */ } static void StaticFunction(int x) { /* 静态成员函数 */ } }; int main() { void (MyClass::*nonStaticPtr)(int) = &MyClass::MyFunction; // 声明非静态成员函数指针 void (*staticPtr)(int) = &MyClass::StaticFunction; // 声明静态成员函数指针 return 0; } ``` #### 要点: - 初始化时,使用 `&ClassName::FunctionName` 获取函数地址。静态成员函数指针可直接赋值,不需要类名作用域。 - 编译错误常见于非静态指针的错误初始化,如未指定对象调用时会出现 "reference to non-static member function must be called"[^2]。 --- ### 🖥 2. 使用示例:非静态成员函数指针 调用非静态成员函数指针时,必须先有一个对象实例,并通过对象指针或对象引用结合特殊语法调用。格式为:`(object.*ptr)(args)` 或 `(objectPtr->*ptr)(args)`。 #### 完整代码示例 ```cpp #include <iostream> class Calculator { public: int add(int a, int b) { return a + b; } // 非静态成员函数 }; int main() { Calculator calc; // 创建对象实例 Calculator* calcPtr = &calc; // 对象指针 // 声明并初始化指针 int (Calculator::*funcPtr)(int, int) = &Calculator::add; // 调用:通过对象实例 int result1 = (calc.*funcPtr)(2, 3); // 输出: 5 // 调用:通过对象指针 int result2 = (calcPtr->*funcPtr)(4, 5); // 输出: 9 std::cout << "result1: " << result1 << ", result2: " << result2 << std::endl; return 0; } ``` #### 解释: - 这里 `funcPtr` 指向 `Calculator::add`,调用时必须使用 `.*` 或 `->*` 运算符与对象关联。 - 如果没有对象实例,试图调用 `funcPtr` 会导致编译错误,如引用[^2]所述。 --- ### 🖥 3. 使用示例:静态成员函数指针 静态成员函数指针类似于普通函数指针,因为它不依赖对象实例。直接使用指针名调用即可:`ptr(args)`。 #### 完整代码示例(参考引用[^3]) ```cpp #include <iostream> class Math { public: static int multiply(int a, int b) { return a * b; } // 静态成员函数 }; int main() { // 声明并初始化指针 int (*funcPtr)(int, int) = &Math::multiply; // 直接调用,无需对象 int result = funcPtr(3, 4); // 等同于 Math::multiply(3, 4) std::cout << "乘法结果: " << result << std::endl; // 输出: 12 return 0; } ``` #### 解释: - 静态成员函数指针 `funcPtr` 的声明和调用方式与普通函数指针一致 ($funcPtr \equiv \text{普通函数指针}$)。 - 这类指针常用于回调函数场景,因为不需要管理对象生命周期,适合解耦设计[^3]。 --- ### 🔄 4. 使用示例:类成员函数指针作为回调函数 非静态成员函数指针需要特殊处理才能用于回调,因为标准函数指针类型不能直接绑定非静态成员。解决方法是使用**包装器**或**lambda函数**。 #### 完整代码示例(基于引用[^4]) ```cpp #include <iostream> #include <functional> // 用于std::function和std::bind class EventHandler { public: void onEvent(int data) { std::cout << "事件处理: " << data << std::endl; } }; // 回调函数类型定义 using Callback = std::function<void(int)>; void triggerEvent(Callback callback, int value) { callback(value); // 调用回调 } int main() { EventHandler handler; // 方法1: 使用std::bind包装非静态成员函数指针 Callback callback1 = std::bind(&EventHandler::onEvent, &handler, std::placeholders::_1); // 方法2: 使用lambda表达式捕获对象 Callback callback2 = [&handler](int data) { handler.onEvent(data); }; triggerEvent(callback1, 100); // 输出: 事件处理: 100 triggerEvent(callback2, 200); // 输出: 事件处理: 200 return 0; } ``` #### 解释: - `std::bind` 或 `lambda` 可以将对象实例与成员函数指针绑定,转换为可调用类型 ($\text{Callback}$)。 - 这种方法避免了直接传递非静态指针的错误,适合事件驱动或接口编程[^4]。 --- ### ⚠️ 5. 注意事项和常见问题 1. **非静态指针调用要求**: 必须提供一个有效的对象实例,否则导致编译错误 "reference to non-static member function must be called"[^2]。 2. **访问权限**: 指针只能访问公有成员函数。私有函数无法通过指针外部访问 ($\text{ClassName::*ptr}$ 受类权限约束)。 3. **性能影响**: 调用非静态指针可能引入间接开销,但在现代编译器中优化良好。 4. **静态 vs 非静态区别**: - 非静态指针:需要对象,指针类型为 `ReturnType (ClassName::*)(Params)`。 - 静态指针:无需对象,指针类型为 `ReturnType (*)(Params)`[^3]。 5. **多线程风险**: 在多线程环境使用对象指针时,需确保对象生命周期安全。 6. **编译器兼容性**: 所有现代C++编译器(GCC、Clang、MSVC)均支持,但初始化语法需准确。 --- ### 💎 总结 - **类成员函数指针**提供灵活指向类成员函数的能力,但必须区分静态与非静态类型。 - 使用时: - 非静态指针:用 `(object.*ptr)` 语法调用。 - 静态指针:像普通函数指针调用。 - 回调场景:使用 `std::bind` 或 `lambda` 包装。 - 实际应用包括事件处理、插件系统等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值