C++类成员函数指针定义与调用示例代码的功能解析
C++类成员函数指针代码段全流程解析
这段代码的核心作用是完成非静态类成员函数的指针定义、绑定、实例调用全链路逻辑,和普通函数指针的语法规则有本质区别,逐段拆解如下:
1. 成员函数指针的声明规则
代码第一行的声明部分结构为 void (M::*pf)(int, int):
- 固定语法格式为:
返回值类型 (类名::*指针变量名)(形参列表) - 语义解释:
pf是一个指针类型,专门用来指向类M的非静态成员函数,被指向的函数必须满足返回值为void、接收两个int类型入参的要求 - 关键语法注意:包裹
*pf的圆括号不能省略,如果去掉括号写成void M::*pf(int, int),会直接被解析成“返回void*类型的成员函数声明”,完全偏离指针定义的本意 - 和普通函数指针的核心差异:必须添加
类名::作用域标识,因为非静态成员函数不属于全局命名空间,独立的普通函数指针没有办法承载类作用域的成员地址。
2. 成员函数指针的地址赋值逻辑
代码中= &M::set_xy的赋值流程:
- 标准取地址写法必须加
&+类名::前缀,即&类名::成员函数名。部分宽松编译器可能支持省略&的写法,但严格遵循C++标准的场景下,直接写M::set_xy不会自动隐式转换为指针值,属于不合法语法 - 这里拿到的不是和普通函数一样的独立入口地址,本质是成员函数在类中的偏移位置。非静态成员函数的逻辑是类级别的共享代码,调用时必须绑定实际实例,这个偏移量会配合实例传入的this指针,定位到实际要执行的函数逻辑
- 绑定完成后,该指针和所有M类的实例解耦:无论哪个M类的实例,都可以通过这个指针调用对应的set_xy方法,因为方法的执行逻辑是统一的。
3. 成员函数指针的实际调用流程
注:代码段中写的
(n*pf)是排版时省略运算符空格的常见写法,实际C++语法里成员指针的调用运算符是.*,也就是标准写法为(n .* pf)——如果真的纯粹按n * pf解析,会被当成对象n和指针pf做乘法运算,完全不具备函数调用语义,属于连写导致的视觉混淆。
- 固定调用语法格式为:
(实例对象 .* 成员函数指针)(实参列表),这里的.*是C++专门为成员指针定义的重载运算符,用来完成“实例和成员函数指针的绑定调用” - 外层的圆括号不能省略:因为函数调用运算符
()的优先级高于解引用相关的运算符,不加括号会被解析成“先执行pf(10,20)的函数调用,再对返回值做解引用”,直接编译报错 - 内部执行逻辑:遇到这段调用代码时,编译器会自动把实例n的地址作为this指针传入绑定的set_xy方法,再把10、20两个实参传递给set_xy的形参,最终执行效果和直接写
n.set_xy(10,20)完全一致 - 补充:如果绑定的是类实例的指针,调用语法会替换为
(实例指针 ->* 成员函数指针)(实参列表),和当前值对象的调用规则对应。
常见语法误区
- 不要把类非静态成员函数指针直接赋值给普通函数指针,二者类型完全不匹配,比如
void (*pf)(int,int) = &M::set_xy;是编译无法通过的 - 不要不绑定实例直接调用成员函数指针,非静态成员函数必须依赖this指针才能访问实例的成员变量,没有实例的调用是非法的
- 不要把类静态成员函数和非静态成员函数的指针规则混淆:静态成员函数没有this指针,它的指针可以直接用普通函数指针类型承载。
内容的提问来源于stack exchange,提问作者adminisnewbie
相关产品推荐
相关产品推荐

