C++函数调用解耦-V1
最近在敲代码的过程中,遇到了一个颇有意思的问题:
如何简单、干净、不留痕迹的完成模块A中函数funA调用模块B中的funB的过程?
首先解释下,什么叫“简单、干净、不留痕迹”。
一般来说funA调用funB最直接的方式无非是,在A文件中包含B的头文件,如果需要的话A库链接B库,然后就可以按如下方式直接调用:
void funA()
funcB()
这种方式的最大问题是,模块A、B之间形成了强依赖,A知道了太多除funB以外的信息,而这些大多是非必须的。我们可以想象一下,funA如果需要调用funB,它只需要知道funB的参数列表与返回值即可,其他都是无关紧要的。
基于这样的“断舍离”视角,很自然会引申出一种解耦策略,使用一张映射表来保存函数对象,通过绑定来注册,然后在需要的时候调用。
using any_function = std::function<void(std::any)>;
class function_register
public:
void regist(const std::string &key, const any_function& func);
void run(const std::string &key, const std::any &);
private:
std::unordered_map<std::string, any_function> function_hub;
定义了一个map,保存了any_function 。 事实上,any_function这个名字起得有点不要脸,当前的表示方式还无法涵盖任意函数类型,首先返回值只能是void,其次参数使用std::any把变参参数列表打包成了一个std::any,有点取巧,当然效率和简洁程度也有损失。这是目前使用的v1版,希望接下来有更简洁的版本。
void plus(const std::any&data)
int a, b;
std::tie(a, b) = std::any_cast<std::pair<int, int>>(data);
std::cout << a << "+" << b << "=" << a + b << std::endl;
void plus_100(const std::any&data)
int a = std::any_cast<int>(data);
std::cout << a << "+" << 100 << "=" << a + 100 << std::endl;
class test_output
public:
void ppp(const std::any &a)
std::cout << std::any_cast<const std::string>(a) << std::endl;
int main()
function_register fr;
test_output to;
fr.regist("plus", std::bind(&plus, std::placeholders::_1));
fr.regist("plus_100", std::bind(&plus_100, std::placeholders::_1));
fr.regist("plus_triple", [](const std::any& triple)
int a, b;
double c;
std::tie(a, b, c) = std::any_cast<std::tuple<int, int, double>>(triple);
std::cout << a << "+" << b << "+" << c << "=" << a + b + c << std::endl;
fr.regist("test_output::ppp", std::bind(&test_output::ppp, &to, std::placeholders::_1));
fr.run("plus", std::make_pair(1, 2));