如何实现类型名跟类型的对应, 我们很容易想到map, 没错, 就是使用map实现的. std::map<std::string, .....>, 等下, 第二部分该填什么类型, 一个函数指针, auto create()? auto只是占位符, 编译器好像不会让你通过吧. 我们需要一种容器, 可以存放所有的类型,  模板.

  由于声明这个容器是并不能包含模板参数, 这里借鉴了boost 库中any的代码, 原理如下:

 class Container {

 private:

     class bridge {

     public:
bridge(){}
virtual ~bridge(){}
virtual void invoke(unsigned long long addr, const std::vector<const char*>& args) = ;
virtual void* instanceOfClass() = ;
}; template<typename ValueType>
class holder: public bridge { public:
virtual void invoke(unsigned long long addr, const std::vector<const char*>& args) override{};
virtual void* instanceOfClass() override{};
}; template<typename ValueType>
class holder<ValueType*>: public bridge { public:
holder(ValueType* item){}
virtual ~holder() {} virtual void invoke(unsigned long long addr, const std::vector<const char*>& args) override{ } virtual void* instanceOfClass() override{ }
}; bridge* content_;
public:
Container(){}
~Container(){
Alloc::dellocate(content_);
} template<typename ValueType>
Container(ValueType* item) { holder<ValueType*>* h = static_cast<holder<ValueType*>*>(Alloc::allocate(sizeof(holder<ValueType*>)));
new(h) holder<ValueType*>(item);
content_ = h;
} // three arguments most, and type are char*
void invoke(unsigned long long addr, const std::vector<const char*>& args) { content_->invoke(addr, args);
} void* instanceOfClass() { return content_->instanceOfClass();
} };

  Container只是一层包装, 隐藏了模板参数, 真正存储类型的是继承bridge的holder子类, bridge提供接口, 由于纯虚函数不能是模板函数, 所以返回实例是必须强制转型为void* 指针, 由客户端再强制转型回来.如何存储一个类类型的信息呢, 最简单, 保存该类型的一个指针变量就行. 其他的交由编译器的模板处理. 然后将类注册, 即插入map中. 可以通过宏来实现.

  好了, 到了最后一步, 函数类型问题. 我们的目标是在配置文件中声明类似的语句:

  <Function name="declation", scale = "Init">

    <Argument>One</Argument>

    <Argument>Two</Argument>

  </Function>

  只要这样声明就能生产 void declation(const Init*, One, Two)这样的函数声明.

  由于文本中只能保存基本的类型, 你不可能用在文本中指定某个参数是指针吧. 还有是函数个数的问题, 我本以为模板的可变参数能起点作用, 结果发现并不是我想要的. 好吧, 所以只能再做一个限制条件, 3个参数最多, 如果你写的函数参数多余三个, 我想你肯定有办法减少参数个数的, 还有参数类型都是字符串, 从字符串到其他基本类型的转换必须由函数自己解决. 这样, 解决思路很清晰了, 首先根据scale类型获取容器, 根据函数名获取地址, 根据参数个数获取函数类型, 最后执行.

  所有的源代码我都上传在github上面, reflect

  补充:

  之前我一直以为该实现反射的方式只能在debug下才有效, 应为debug下编译器会玩可执行文件中加入大量的调试信息, 当使用release版本时, 并没有这些编译信息, 或许可以使用之前保存过的信息, 但可能会对内存地址有所影响. 之后我详细了解了elf文件格式后, 发现并不会影响, 至少我目前的测试是没有影响的. debug时是将调试信息以dwarf格式的段添加到可执行文件后, 而并不是随机穿插在程序中, 所以只有release时代码并没有修改, 注意宏的修改, 就可以使用debug时保存下来的调试信息.当我发现这个时有点小兴奋, 他解除了一个限制条件, 使得这种想法或许可以有更大的实用之处.

  

  最后再说点什么:

  这是自己第一次写博客, 自从上了大学以后, 没学过语文, 以前并不知道语文是这么重要, 直达现在发现自己并不能将自己想要说的流畅地, 有层次地表达出来, 写下来. 这几篇博客修修补补还是花了自己一点时间. 如果你在看完之后, 笑道这都写了写什么东西啊, 我也并不会介意的. 以前是懒与去经营自己的博客, 当发现自己写出属于自己的博客时, 还是挺有满足感的, 我也会继续写下去, 继续锻炼, 或许多年以后翻翻自己写过的东西, 回信一下自己当时的所思所想, 也将是已将很有趣的事情吧.

一种实现C++反射功能的想法(三)的更多相关文章

  1. 一种实现C++反射功能的想法(一)

    Java的反射机制很酷, 只需知道类的名字就能够加载调用. 这个功能很实用, 想象一下, 用户只需指定类的名称, 就可以动态绑定类型, 而且只需通过字符串指定, 字符串的使用可以使得用户的修改只需修改 ...

  2. 一种实现C++反射功能的想法(二)

    在介绍我的思路前, 让我们准备下预备知识 C++是怎么实现类函数的绑定的. 我们知道类的非静态成员函数是存储在全局区, 并在内存中只保存一份副本. 我们调用非静态成员函数是通过类对象进行调用. 那么如 ...

  3. 使用反射功能在Unity运行状态通过Inspector面板修改字段和调用方法

    使用反射功能在Unity运行状态通过Inspector面板修改字段和调用方法 效果展示 一个很简单的组件脚本 运行状态在Inspector面板可以随便修改字段和调用方法 方法调用日志 设计由来 最近在 ...

  4. asp.net导出excel-一行代码实现excel、xml、pdf、word、html、csv等7种格式文件导出功能而且美观-SNF快速开发平台

    分享: 腾讯微博  新浪微博   搜狐微博   网易微博  腾讯朋友  百度贴吧  豆瓣   QQ好友  人人网 作者:王春天  原文地址:http://www.cnblogs.com/spring_ ...

  5. Java反射获取class对象的三种方式,反射创建对象的两种方式

    Java反射获取class对象的三种方式,反射创建对象的两种方式 1.获取Class对象 在 Java API 中,提供了获取 Class 类对象的三种方法: 第一种,使用 Class.forName ...

  6. Java反射机制demo(三)—获取类中的构造函数

    Java反射机制demo(三)—获取类中的构造函数 1,获取类中所有的构造函数 如下面的代码中所示,这个类中显式的构造函数有五个. 空构造: public UserInfo() 带参构造有四个: pu ...

  7. 设计模式之抽象工厂模式(附带类似反射功能的实现/c++)

    问题描述 假设我们要开发一款游戏, 当然为了吸引更多的人玩, 游戏难度不能太大(让大家都没有信心了,估计游戏也就没有前途了),但是也不能太简单(没有挑战性也不符合玩家的心理).于是我们就可以采用这样一 ...

  8. 在c++中实现反射的初步想法

    最近在思考如何在c++中实现反射.事情的起因是这样的:我们服务器是用c++开发的,如果需要写一些测试用的GM指令的话,需要编写完GM代码后重新编译并且重启进程,工序繁琐且比较耗时.因此就有了想用脚本( ...

  9. 单例模式的几种实现And反射对其的破坏

    一 单例模式概述 (一) 什么是单例模式 单例模式属于创建型模式之一,它提供了一种创建对象的最佳方式 在软件工程中,创建型模式是处理对象创建的设计模式,试图根据实际情况使用合适的方式创建对象.基本的对 ...

随机推荐

  1. BZOJ1609: [Usaco2008 Feb]Eating Together麻烦的聚餐

    1609: [Usaco2008 Feb]Eating Together麻烦的聚餐 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 938  Solved ...

  2. 【转】android官方侧滑菜单DrawerLayout详解

    原文网址:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0925/1713.html drawerLayout是Support ...

  3. Delphi 用Web App Debugger简单调试ISAPI 转

    用Web App Debugger简单调试ISAPI   以isapi为例: 1.新建一个project,用isapi/nsapi: 2.remove这个project中所有的unit: 3.加进你用 ...

  4. Unity 的 unitypackage 的存放路径

    Windows,C:\Users\<username>\AppData\Roaming\Unity\Asset Store Mac OS X,~/Library/Unity/Asset S ...

  5. MT9M021/MT9M031总结

    MT9M021/MT9m031在低光照度下和捕捉移动场景有非常优异的表现,属于近红外摄像头, S1: Aptina's MT9M021/MT9M031 sensor is capable of a m ...

  6. second blog编程之美------控制cpu曲线

    先贴程序: 以前看过这个算法, 不过没什么印象,大概记得它利用while循环来控制cpu利用率 #include int main(int argc,char*argv[]) {         wh ...

  7. 放爬虫nginx

    禁止火狐浏览器访问 例子

  8. 传统IO与NIO区别二

    nio是new io的简称,从jdk1.4就被引入了.现在的jdk已经到了1.6了,可以说不是什么新东西了.但其中的一些思想值得我来研究.这两天,我研究了下其中的套接字部分,有一些心得,在此分享.  ...

  9. javascript中的稀疏数组(sparse array)和密集数组

    学习underscore.js数组相关API的时候.遇到了sparse array这个东西,曾经没有接触过. 这里学习下什么是稀疏数组和密集数组. 什么是密集数组呢?在java和C语言中,数组是一片连 ...

  10. 【MongoDB】在windows平台下mongodb的分片集群(五)

    本篇接着上面的四篇继续讲述在window平台下mongodb的分片集群搭建. 在分片集群中也照样能够创建索引,创建索引的方式与在单独数据库中创建索引的方式一样.因此这不再多说.本篇主要聚焦在分片键的选 ...