news 2026/4/18 1:00:48

C++成员指针在库设计中的实际案例

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++成员指针在库设计中的实际案例

成员指针(数据成员指针和成员函数指针)在库设计中常用于实现编译期类型安全运行时动态访问以及泛型算法。下面通过几个实际案例展示其典型应用。


案例1:通用属性访问器(Property System)

目标:定义一个Property类,能够绑定到某个类的某个数据成员,并提供统一的get/set接口,支持批量操作。

#include<iostream>#include<vector>template<typenameClass,typenameType>classProperty{Type Class::*member;// 数据成员指针public:Property(Type Class::*m):member(m){}Typeget(constClass&obj)const{returnobj.*member;}voidset(Class&obj,constType&value)const{obj.*member=value;}};// 使用示例structPerson{std::string name;intage;};intmain(){Person p{"Alice",25};Property<Person,std::string>nameProp(&Person::name);Property<Person,int>ageProp(&Person::age);std::cout<<nameProp.get(p)<<" is "<<ageProp.get(p)<<std::endl;// Alice is 25ageProp.set(p,26);std::cout<<ageProp.get(p)<<std::endl;// 26// 批量操作:遍历多个属性std::vector<Property<Person,int>>intProps;intProps.emplace_back(&Person::age);// 可以添加更多 int 成员...for(auto&prop:intProps){prop.set(p,0);}std::cout<<ageProp.get(p)<<std::endl;// 0}

设计价值

  • 将成员访问封装成对象,便于存储、传递和批量操作。
  • 可用于实现图形界面的“属性编辑器”,运行时通过字符串名查找对应的Property对象。

案例2:简易对象关系映射(ORM)

目标:定义一个通用Table模板,能够将 C++ 结构体映射到 SQL 表的行,使用成员指针读写字段,自动生成 INSERT/UPDATE 语句。

#include<iostream>#include<string>#include<vector>#include<sstream>// 字段描述template<typenameClass,typenameType>structField{std::string name;Type Class::*ptr;// 数据成员指针Field(conststd::string&n,Type Class::*p):name(n),ptr(p){}};// 表映射template<typenameClass>classTable{std::string tableName;std::vector<FieldBase*>fields;// 简化:实际用类型擦除或 variantpublic:Table(conststd::string&name):tableName(name){}template<typenameType>voidaddField(conststd::string&colName,Type Class::*ptr){fields.push_back(newField<Class,Type>(colName,ptr));}std::stringgenerateInsert(constClass&obj)const{std::stringstream ss;ss<<"INSERT INTO "<<tableName<<" (";for(size_t i=0;i<fields.size();++i){if(i)ss<<",";ss<<fields[i]->name;}ss<<") VALUES (";for(size_t i=0;i<fields.size();++i){if(i)ss<<",";// 通过成员指针获取值(需要类型转换,这里简化)// 实际实现需要根据类型生成正确字面量}ss<<")";returnss.str();}};// 使用示例(简化,只演示结构)structUser{intid;std::string name;};intmain(){Table<User>userTable("users");userTable.addField("id",&User::id);userTable.addField("name",&User::name);User u{1,"Alice"};// std::cout << userTable.generateInsert(u) << std::endl;// 输出:INSERT INTO users (id,name) VALUES (1,'Alice');}

设计价值

  • 成员指针存储了字段在对象内的偏移量,运行时可以读写任意对象的该字段。
  • ORM 库(如 ODB、sqlpp11)底层大量使用成员指针实现编译期反射。

案例3:信号槽(Signal-Slot)简化实现

目标:实现一个简单的信号槽机制,槽可以是任意类的成员函数(使用成员函数指针)。

#include<functional>#include<vector>#include<iostream>// 类型擦除的槽容器classSlotBase{public:virtual~SlotBase()=default;virtualvoidinvoke()=0;};template<typenameClass>classSlot:publicSlotBase{Class*obj;void(Class::*method)();// 成员函数指针public:Slot(Class*o,void(Class::*m)()):obj(o),method(m){}voidinvoke()override{(obj->*method)();}};classSignal{std::vector<SlotBase*>slots;public:template<typenameClass>voidconnect(Class*obj,void(Class::*method)()){slots.push_back(newSlot<Class>(obj,method));}voidemit(){for(auto*slot:slots)slot->invoke();}~Signal(){for(auto*s:slots)deletes;}};// 使用示例classLogger{public:voidinfo(){std::cout<<"Info logged\n";}voidwarn(){std::cout<<"Warning logged\n";}};intmain(){Signal sig;Logger logger;sig.connect(&logger,&Logger::info);sig.connect(&logger,&Logger::warn);sig.emit();// 输出两行}

设计价值

  • 成员函数指针允许将任何类的成员函数注册为回调,无需继承自某个接口。
  • 现代库(如boost::signals2Qt的 moc 本质上也是类似,但用元对象编译器扩展了语法)。

案例4:通用序列化 / 遍历成员

目标:实现一个能遍历对象所有指定类型成员的函数,用于序列化、哈希、打印等。

#include<iostream>#include<tuple>#include<string>// 辅助:遍历成员指针元组template<typenameClass,typename...Types>voidforEachMember(Class&obj,std::tuple<Types Class::*...>members,auto&&func){std::apply([&](auto...ptrs){(func(obj.*ptrs),...);},members);}// 定义结构体及其成员指针元组structPoint{intx,y;std::string label;};intmain(){Point p{10,20,"origin"};automembers=std::make_tuple(&Point::x,&Point::y,&Point::label);// 打印所有成员forEachMember(p,members,[](constauto&value){std::cout<<value<<" ";});// 输出:10 20 origin// 序列化为 JSON(简化)std::string json="{";forEachMember(p,members,[&](constauto&value){// 实际需处理不同类型,此处仅示意json+=std::to_string(value)+",";});json.back()='}';std::cout<<json<<std::endl;// {10,20,origin}}

设计价值

  • 利用成员指针元组实现编译期反射,避免宏或代码生成器。
  • 可用于实现通用的operator<<hash组合、对象比较等。

案例5:多态委托(Polymorphic Delegate)

目标:实现一个可以存储任意类成员函数(参数/返回值相同)的委托,并支持直接调用。

#include<memory>#include<iostream>template<typenameRet,typename...Args>classDelegate{structCallableBase{virtual~CallableBase()=default;virtualRetinvoke(Args...args)=0;};template<typenameClass>structCallable:CallableBase{Class*obj;Ret(Class::*method)(Args...);Callable(Class*o,Ret(Class::*m)(Args...)):obj(o),method(m){}Retinvoke(Args...args)override{return(obj->*method)(args...);}};std::unique_ptr<CallableBase>callable;public:template<typenameClass>Delegate(Class*obj,Ret(Class::*method)(Args...)):callable(std::make_unique<Callable<Class>>(obj,method)){}Retoperator()(Args...args)const{returncallable->invoke(args...);}};// 使用示例classCalculator{public:intadd(inta,intb){returna+b;}intsub(inta,intb){returna-b;}};intmain(){Calculator calc;Delegate<int,int,int>d(&calc,&Calculator::add);std::cout<<d(5,3)<<std::endl;// 8d=Delegate<int,int,int>(&calc,&Calculator::sub);std::cout<<d(5,3)<<std::endl;// 2}

设计价值

  • 类似于std::function但更轻量,且仅支持成员函数(或可扩展支持普通函数)。
  • 用于事件系统、回调管理、命令模式等。

总结:成员指针在库设计中的优势

应用场景使用的成员指针类型核心价值
属性系统数据成员指针类型安全的成员访问封装,支持运行时动态访问
ORM / 序列化数据成员指针存储偏移量,无需侵入式宏或代码生成,即可读写对象字段
信号槽 / 事件成员函数指针允许任意类的成员函数作为回调,解耦模块
泛型遍历 / 反射数据成员指针元组编译期遍历对象成员,实现通用算法(打印、哈希、比较)
多态委托成员函数指针类型擦除 + 成员指针,实现类似std::function的轻量级委托

这些案例都体现了成员指针的核心理念:将“成员在类中的位置”作为一等公民,使得算法可以独立于具体对象,同时保持类型安全。在需要运行时操作对象成员编译期绑定类型的场景下,成员指针是不可替代的工具。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 0:51:17

ngx_process_get_status

1 定义 ngx_process_get_status 函数 定义在 ./nginx-1.24.0/src/os/unix/ngx_process.cstatic void ngx_process_get_status(void) {int status;char *process;ngx_pid_t pid;ngx_err_t err;ngx_int_t i;ngx_uint_t one;o…

作者头像 李华
网站建设 2026/4/18 0:50:14

贾子逆算子(KIO)全解:从理论定义到工程修正的完整实现

贾子逆算子&#xff08;KIO&#xff09;全解&#xff1a;从理论定义到工程修正的完整实现摘要贾子逆算子&#xff08;KIO&#xff09;是2026年初提出的大语言模型主动式幻觉抑制元算子&#xff0c;通过逆向映射与因果追溯实现逻辑校准&#xff0c;推动模型从“概率生成”转向“…

作者头像 李华
网站建设 2026/4/18 0:39:31

如何实现跨设备音频共享?Scream虚拟声卡网络传输终极指南

如何实现跨设备音频共享&#xff1f;Scream虚拟声卡网络传输终极指南 【免费下载链接】scream Virtual network sound card for Microsoft Windows 项目地址: https://gitcode.com/gh_mirrors/sc/scream 你是否曾想过将电脑音频无线传输到其他设备播放&#xff1f;无论是…

作者头像 李华
网站建设 2026/4/18 0:39:27

微机原理实验一代码逐行“翻译”:从汇编指令到C语言思维帮你理解

从汇编到C&#xff1a;微机原理实验代码的思维转换指南 1. 汇编与C语言的桥梁搭建 第一次接触微机原理实验的同学们&#xff0c;往往会被那些密密麻麻的汇编指令弄得晕头转向。mov ax, data、int 21h这些看似神秘的代码&#xff0c;其实都有其对应的C语言思维模式。让我们从一个…

作者头像 李华