C++类成员指针的实现示例 一、类成员指针的核心定位类成员指针是C中专门指向“类的成员”而非具体对象的成员的特殊指针和普通指针的核心区别普通指针直接指向内存中的某个地址如变量、函数的入口地址成员指针不直接指向内存地址而是存储“成员在类中的偏移量”必须绑定具体对象/对象指针后才能访问因为类的成员属于对象而非类本身。二、数据成员指针1. 定义语法指向类的非静态数据成员的指针语法格式// 格式类名::* 指针变量名类型 类名::* 数据成员指针名 类名::数据成员名;2. 完整示例可直接运行12345678910111213141516171819202122232425262728293031323334#include iostreamusingnamespacestd;classPerson {public:string name;intage;staticintcount;// 静态数据成员特殊情况};intPerson::count 0;// 静态成员初始化intmain() {// 1. 定义并赋值指向Person的age成员intPerson::*p_age Person::age;// 指向Person的name成员string Person::*p_name Person::name;// 2. 绑定对象访问用.*运算符Person p1{Alice, 20};cout Name: p1.*p_name endl;// 输出Alicecout Age: p1.*p_age endl;// 输出20// 3. 绑定对象指针访问用-*运算符Person* p2 p1;p2-*p_age 21;// 修改agecout New Age: p2-*p_age endl;// 输出21// 4. 静态数据成员指针特殊和普通指针一样int* p_count Person::count;// 无需Person::*直接用普通指针*p_count 100;cout Count: Person::count endl;// 输出100return0;}3. 关键注意点数据成员指针的类型必须严格匹配如int Person::*不能指向string Person::*静态数据成员不属于对象因此指向静态数据成员的指针是普通指针而非成员指针空类/无数据成员的类其数据成员指针的偏移量为0但依然是合法的成员指针。三、成员函数指针1. 定义语法指向类的非静态成员函数的指针语法格式需匹配返回值、参数列表、const/volatile限定// 格式返回值 (类名::*)(参数列表) [const/volatile]返回值 (类名::* 函数指针名)(参数列表) [const] 类名::成员函数名;2. 完整示例含const成员函数1234567891011121314151617181920212223242526272829303132#include iostream#include stringusingnamespacestd;classCalculator {public:intadd(inta,intb) {returna b; }intsub(inta,intb)const{returna - b; }// const成员函数staticintmul(inta,intb) {returna * b; }// 静态成员函数};intmain() {// 1. 指向非const成员函数int(Calculator::*p_add)(int,int) Calculator::add;// 2. 指向const成员函数必须加const限定int(Calculator::*p_sub)(int,int)const Calculator::sub;// 3. 绑定对象调用.*运算符Calculator calc;cout Add: (calc.*p_add)(10, 5) endl;// 输出15cout Sub: (calc.*p_sub)(10, 5) endl;// 输出5// 4. 绑定对象指针调用-*运算符Calculator* p_calc calc;cout Add via ptr: (p_calc-*p_add)(20, 3) endl;// 输出23// 5. 静态成员函数指针特殊和普通函数指针兼容int(*p_mul)(int,int) Calculator::mul;cout Mul: p_mul(4, 5) endl;// 输出20return0;}3. 关键注意点成员函数指针的括号不可省略(calc.*p_add)(10,5)不能写成calc.*p_add(10,5)运算符优先级问题.和-*优先级低于()const成员函数的指针必须加const限定否则不匹配如int (Calculator::*)(int,int) const不能赋值给int (Calculator::*)(int,int)成员函数隐含this指针因此必须绑定对象才能调用静态成员函数无this故无需绑定成员函数指针的大小可能大于普通指针如64位系统可能占16字节因为需要存储函数地址this调整信息多继承场景。四、将成员函数用作可调用对象成员函数指针本身不能直接作为“无上下文的可调用对象”如传给std::thread、std::function、std::for_each等必须绑定对象/this指针常用3种方式1. 方式1std::bindC11及以上最经典的方式将成员函数与对象绑定生成可调用的函数对象1234567891011121314151617181920#include iostream#include functional // 必须包含usingnamespacestd;classPrinter {public:voidprint(string msg,intnum) {cout msg : num endl;}};intmain() {Printer p;// 绑定成员函数对象固定部分参数也可留空参数用placeholdersauto func bind(Printer::print, p,Number, placeholders::_1);// 调用只需传未绑定的参数func(100);// 输出Number: 100return0;}2. 方式2std::function适配将成员函数指针对象封装为std::function适配通用可调用接口123456789101112131415161718192021#include iostream#include functionalusingnamespacestd;classMath {public:intsquare(intx) {returnx * x; }};intmain() {Math m;// 封装为std::function参数列表要匹配成员函数隐含this已绑定functionint(int) f bind(Math::square, m, placeholders::_1);cout f(5) endl;// 输出25// 也可直接用lambda更简洁见方式3functionint(int) f2 [m](intx) {returnm.square(x); };cout f2(6) endl;// 输出36return0;}3. 方式3lambda表达式包裹推荐C11最简洁、易读的方式用lambda捕获对象/this包裹成员函数调用1234567891011121314151617181920212223242526272829303132333435#include iostream#include thread // 用于演示线程调用成员函数usingnamespacestd;classWorker {public:voidwork(intid) {cout Worker id is running endl;}};intmain() {Worker w;// 1. 普通调用lambda捕获对象auto func [w]() { w.work(1); };func();// 输出Worker 1 is running// 2. 线程调用成员函数核心场景threadt([w]() { w.work(2); });t.join();// 输出Worker 2 is running// 3. 捕获this成员函数内调用classTest {public:voidcall_self() {auto f [this]() {this-work(3); };f();// 输出Worker 3 is running}voidwork(intid) { cout Test Worker id endl; }};Test tst;tst.call_self();return0;}4. 典型场景成员函数作为算法的回调1234567891011121314151617181920212223#include iostream#include vector#include algorithmusingnamespacestd;classFilter {public:boolis_even(intx) {returnx % 2 0; }};intmain() {vectorint nums {1,2,3,4,5};Filter f;// 用lambda包裹成员函数作为find_if的谓词auto it find_if(nums.begin(), nums.end(), [f](intx) {returnf.is_even(x);});if(it ! nums.end()) {cout First even number: *it endl;// 输出2}return0;}五、核心对比成员指针 vs 普通指针特性普通指针如int*、void(*)(int)类成员指针如int A::、void (A::)(int)指向目标内存地址变量/函数入口类成员的偏移量需绑定对象大小固定64位8字节可能更大如多继承场景16字节调用/访问方式直接解引用*p、p()需绑定对象用.* / -* 运算符静态成员适配完全兼容静态成员的指针等价于普通指针this指针无非静态成员函数指针隐含this需绑定对象总结成员指针本质存储类成员的偏移量而非直接内存地址必须绑定对象才能访问/调用语法关键数据成员指针用类名::*成员函数指针需匹配返回值/参数/const限定调用用.*/-*可调用对象适配优先用lambda表达式包裹成员函数简洁无坑其次用std::bind避免直接传递成员函数指针特殊情况静态成员的指针等价于普通指针无需绑定对象即可使用。