一种实现C++反射功能的想法(三)
如何实现类型名跟类型的对应, 我们很容易想到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++反射功能的想法(三)的更多相关文章
- 一种实现C++反射功能的想法(一)
Java的反射机制很酷, 只需知道类的名字就能够加载调用. 这个功能很实用, 想象一下, 用户只需指定类的名称, 就可以动态绑定类型, 而且只需通过字符串指定, 字符串的使用可以使得用户的修改只需修改 ...
- 一种实现C++反射功能的想法(二)
在介绍我的思路前, 让我们准备下预备知识 C++是怎么实现类函数的绑定的. 我们知道类的非静态成员函数是存储在全局区, 并在内存中只保存一份副本. 我们调用非静态成员函数是通过类对象进行调用. 那么如 ...
- 使用反射功能在Unity运行状态通过Inspector面板修改字段和调用方法
使用反射功能在Unity运行状态通过Inspector面板修改字段和调用方法 效果展示 一个很简单的组件脚本 运行状态在Inspector面板可以随便修改字段和调用方法 方法调用日志 设计由来 最近在 ...
- asp.net导出excel-一行代码实现excel、xml、pdf、word、html、csv等7种格式文件导出功能而且美观-SNF快速开发平台
分享: 腾讯微博 新浪微博 搜狐微博 网易微博 腾讯朋友 百度贴吧 豆瓣 QQ好友 人人网 作者:王春天 原文地址:http://www.cnblogs.com/spring_ ...
- Java反射获取class对象的三种方式,反射创建对象的两种方式
Java反射获取class对象的三种方式,反射创建对象的两种方式 1.获取Class对象 在 Java API 中,提供了获取 Class 类对象的三种方法: 第一种,使用 Class.forName ...
- Java反射机制demo(三)—获取类中的构造函数
Java反射机制demo(三)—获取类中的构造函数 1,获取类中所有的构造函数 如下面的代码中所示,这个类中显式的构造函数有五个. 空构造: public UserInfo() 带参构造有四个: pu ...
- 设计模式之抽象工厂模式(附带类似反射功能的实现/c++)
问题描述 假设我们要开发一款游戏, 当然为了吸引更多的人玩, 游戏难度不能太大(让大家都没有信心了,估计游戏也就没有前途了),但是也不能太简单(没有挑战性也不符合玩家的心理).于是我们就可以采用这样一 ...
- 在c++中实现反射的初步想法
最近在思考如何在c++中实现反射.事情的起因是这样的:我们服务器是用c++开发的,如果需要写一些测试用的GM指令的话,需要编写完GM代码后重新编译并且重启进程,工序繁琐且比较耗时.因此就有了想用脚本( ...
- 单例模式的几种实现And反射对其的破坏
一 单例模式概述 (一) 什么是单例模式 单例模式属于创建型模式之一,它提供了一种创建对象的最佳方式 在软件工程中,创建型模式是处理对象创建的设计模式,试图根据实际情况使用合适的方式创建对象.基本的对 ...
随机推荐
- HDU 5927 Auxiliary Set 【DFS+树】(2016CCPC东北地区大学生程序设计竞赛)
Auxiliary Set Time Limit: 9000/4500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Tot ...
- Unity3D学习笔记-------小地图制作
制作小地图首先需要两个贴图:第一个贴图是小地图的背景贴图,它应当是从y轴向下俯视截取的贴图:第二个贴图是主角位置贴图,它应当是在背景贴图之上的小型矩形. 1 using UnityEngine; 2 ...
- iOS类的继承关系
- tyvj P1952 Easy(递推+期望)
P1952 Easy 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 某一天WJMZBMR在打osu~~~但是他太弱逼了,有些地方完全靠运气:(我们来简化一下 ...
- JavaScript高级程序设计19.pdf
注册处理程序 navigator.registerContentHandler("applicat/rss+xml","http://www.somereader.com ...
- 大众点评网王宏:从.Net迁移向Java平台 - 51CTO.COM
大众点评网王宏:从.Net迁移向Java平台 - 51CTO.COM 大众点评网王宏:从.Net迁移向Java平台
- poj 1847 Tram【spfa最短路】
Tram Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 12005 Accepted: 4365 Description ...
- MySQL 5.7版本安装教程-踩坑总结
下载 MySQL下载地址 选择下载64位(看自己电脑是32位还是64位) 点击下载之后,它会让你登录,没有Oracle账户,跟着它的步骤注册一个就好了. 安装 打开下载好的压缩包解压到你的某一目录下, ...
- ubuntu下管理android手机
1.安装adb apt-get install android-tools-adb 2.配置 1)运行lsusb Bus 001 Device 002: ID 8087:0024 Intel Corp ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(40)-精准在线人数统计实现-【过滤器+Cache】
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(40)-精准在线人数统计实现-[过滤器+Cache] 系列目录 上次的探讨没有任何结果,我浏览了大量的文章 ...