C++中如何将多个相似Setter函数合并为通用函数?
解决方案:用通用模板函数封装重复逻辑
完全可以通过编写通用模板函数来封装foo(b)、调用B成员函数、bar(b)这三段重复逻辑,只需要将B的成员函数和对应参数作为参数传入即可,大幅减少代码冗余。
先看原来的冗余代码示例
假设你的类结构大致如下:
#include <string> class B { public: void doSomethingWithID(int id) { /* 具体业务逻辑 */ } void doSomethingWithName(const std::string& name) { /* 具体业务逻辑 */ } void doSomethingWithNumber(double num) { /* 具体业务逻辑 */ } }; class A { private: B b; void foo(B& obj) { /* 复杂的前置处理逻辑 */ } void bar(B& obj) { /* 复杂的后置处理逻辑 */ } public: void setID(int id) { foo(b); b.doSomethingWithID(id); bar(b); } void setName(const std::string& name) { foo(b); b.doSomethingWithName(name); bar(b); } void setNumber(double num) { foo(b); b.doSomethingWithNumber(num); bar(b); } // 更多重复的setter函数... };
优化后的通用实现
通过模板函数封装公共逻辑,只需要在每个setter中调用这个通用函数即可:
#include <string> #include <functional> // 用于std::invoke(C++17+) class B { public: void doSomethingWithID(int id) { /* 具体业务逻辑 */ } void doSomethingWithName(const std::string& name) { /* 具体业务逻辑 */ } void doSomethingWithNumber(double num) { /* 具体业务逻辑 */ } }; class A { private: B b; void foo(B& obj) { /* 复杂的前置处理逻辑 */ } void bar(B& obj) { /* 复杂的后置处理逻辑 */ } // 通用set模板:兼容任意B的成员函数和参数列表 template<typename Func, typename... Args> void genericSet(Func&& func, Args&&... args) { foo(b); // std::invoke支持成员函数指针、lambda等多种可调用对象 std::invoke(std::forward<Func>(func), b, std::forward<Args>(args)...); bar(b); } public: void setID(int id) { genericSet(&B::doSomethingWithID, id); } void setName(const std::string& name) { genericSet(&B::doSomethingWithName, name); } void setNumber(double num) { genericSet(&B::doSomethingWithNumber, num); } // 新增setter只需一行代码,比如新增setAge: // void setAge(int age) { genericSet(&B::doSomethingWithAge, age); } };
关键细节说明
- 模板参数与完美转发:使用
typename... Args可变参数模板和std::forward,确保参数能以正确的类型传递给B的成员函数,避免不必要的拷贝。 - std::invoke的作用:C17引入的
std::invoke可以统一处理成员函数指针、普通函数、lambda等可调用对象,让通用函数更灵活。如果你的项目基于C11/14,可以直接用成员函数指针调用语法替代:(b.*func)(std::forward<Args>(args)...); - 维护性提升:后续修改
foo或bar的逻辑时,只需要修改genericSet中的一处代码;新增setter时,只需要调用genericSet并传入对应的B成员函数和参数即可,完全避免重复编写前置/后置逻辑。
内容的提问来源于stack exchange,提问作者RocketSearcher
相关产品推荐
相关产品推荐

