asp.net 网站开发 pdf,苏州市规划建设局网站,ciid中国室内设计大奖赛,文案网站策划书一、函数反射
在实际的编程中#xff0c;类和结构体应用最多#xff0c;但也最难。这里先分析函数反射#xff0c;类和结构体放到后面在分析。函数是什么#xff1f;其实在PC看来就是一个地址#xff0c;在编译顺看来就是一个符号#xff08;废话啊#xff09;。函数反…一、函数反射
在实际的编程中类和结构体应用最多但也最难。这里先分析函数反射类和结构体放到后面在分析。函数是什么其实在PC看来就是一个地址在编译顺看来就是一个符号废话啊。函数反射的应用也非常多比如通过一个字符串来得到相关的API调用。这个在一些动态调用中非常有用。 举一个简单例子一般C/C开发者都使用过函数指针而函数指针就可以实现一些和函数反射有点类似的功能。一般函数指针在应用时都是通过值来判断是什么来决定调用哪个函数指针这些值其实就可以是字符串类型这就和反射很像了。但函数指针的实现有点小问题在于一个函数指针其特征名称、参数个数、参数类型基本就定了下来。这就不如反射灵活了。 有的开发者可能说可以使用变参、变参模板啊。非常棒。
二、实现方式
先实现一个初级版本通过std:function来实现一个映射版本
#include iostream
#include unordered_map
#include functional
#include stringvoid getData(int t)
{std::cout call getData function,pars is:t std::endl;
}
void getContent(int t)
{std::cout call getContent function,pars is:t std::endl;
}std::unordered_mapstd::string, std::functionvoid(int) umap;
void initMap()
{umap.emplace(getData,getData);umap.emplace(getContent,getContent);
}int main()
{initMap();int d 100;if (umap.count(getData)){auto func umap[getData];func(d);}std::cout end std::endl;
}代码很简单但也很容易看明白。可前面提到过了这种方法局限性还是有的无法实现不同参数和参数类型的函数。这里有一种取巧的方法可以用一个包含std::any的容器std::vector来组织一下但这个就有一个问题处理起来还是不方便。网上还有使用json字符串的这个说法更麻烦了。如果本身反射就带着json处理还好否则写个简单应用还需要带个json库可就麻烦了。
三、利用模板万能函数
在前面分析过万能函数可以在这个基础上实现一个动态处理函数反射的类
#pragma once
#include string
#include unordered_maptemplate class T, class R, typename... Args
class CppDelegate
{R(T::* func_)(Args...);//万能函数typedef decltype(func_) FUNC;//using FuncGloabl R *(*)(Args...);public:CppDelegate() {}void AddFunction(T *t,const std::string funcname, FUNC func ){umap_.emplace(funcname,func);umap1_.emplace(funcname,t);}templatetypename ...ArgsR StartFunc(const std::string funcname,Args...args){auto type this-getClass(funcname);auto func this-getFunc(funcname);if (type ! nullptr func ! nullptr){return (type-*func)(std::forwardArgs(args) ...);}return R();}
private:FUNC getFunc(const std::string funcname){if (umap_.count(funcname) 0){return umap_[funcname];}return nullptr;}T* getClass(const std::string name){if (umap1_.count(name) 0){return umap1_[name];}return nullptr;}private:std::unordered_mapstd::string, FUNC umap_;std::unordered_mapstd::string, T* umap1_;
};
class Data
{
public:Data() {}~Data() default;
public:int GetData(int a) { std::cout call getData function,a value: a std::endl; return 0; };int GetContent(int a, int b) { std::cout call getContent function: std::endl; return 0; };
};
Data* d new Data;
void testReflect()
{CppDelegateData, int,int cpp;cpp.AddFunction(d,getData,Data::GetData);auto f cpp.StartFunc(getData,100);std::cout f is: std::endl;
}
void testVoid() {return void();
}
int main()
{testVoid();//这个在VS中没有问题testReflect();return 0;
}其实如果只是适配静态和全局函数这个就非常简单了这里需要适配类成员函数所以比较麻烦。上面的代码还有几个问题 1、不同类的不同函数如何存储在一个容器中 2、return R()如何处理void 等特殊情况 3、如何保证t*的生命周期 解决其来也有办法只是怎么看更优雅一些。第一个可以在调用类上再抽象一层第二个可以用概念或者SFINAE控制第三个就比较麻烦了不过目前这样做也可以保证基本使用。
四、总结
不断的抽象实现可以保证设计上的依赖于抽象而不依赖于实现也就使得代码更有普适性。但多层次的抽象导致的结果可能是代码阅读上的困难和维护上不方便。这个就是仁者见仁了一般来说对于库等升级比较正式而且不怎么频繁的项目可以尽量抽象而对于应用层抽象要适当。 不过在现在的环境下就根据情况自己选择吧。