本专栏文章列表
本系列文章属 西风逍遥游 原创,转载请注明出处:
西风世界 http://blog.csdn.net/sun_xiaofan
六、C++也能反射
今天我们来探讨C++的反射问题,缺乏反射机制一直是C++的大问题,很多系统的设计时,需要根据外部资源文件的定义,动态的调用内部的函数和接口,如果没有反射,将很难将外部的数据,转换为内部的方法。
Java和.net的反射机制很容易实现,由于其动态语言的特性,在编译时就存储了大量的元数据,而在动态装载时,也是根据这些元数据载入的模块。由于C++缺乏这些信息,往往并不能很好的动态装载和链接。操作系统为了实现C和C++的动态装载功能,特意设计了动态链接库,将符号表保存在动态库中,运行时重定位代码,然后进行链接操作。而这是操作系统实现的,并不能很好的被用在用户工程中,所以我们有必要自己构建一套元数据集合,保存反射所需的内容。
反射的原理
反射的核心就是根据字符串名字,创建对应的类或者调用对应类的方法,为此,我们使用C++中的map
std::map<std::string, meta_class*>
meta_class 是保存一个类中的关键元数据用的类,可以支持反射构造,反射调用函数等功能。
meta_func 是保存一个方法的关键信息类,但由于方法有不定的参数和返回类型,我们使用模板的方式,将一个抽象存储的成员函数指针,转换为我们确定类型的成员函数指针,然后再去调用,达到动态调用的目的:
template <typename T, typename R, typename... Args>
R Call(T* that, Args... args) {
R (T::*mp)();
mp = *((R (T::**)())func_pointer);
return (that->*mp)(args...);
}
这里的代码十分混乱,如果你没学过C的函数指针的话,建议先去补习一下函数指针的定义和用法。
这里涉及到的是成员函数指针的传递,一会儿将会详细讲解如何传递任意一个函数指针。
反射类对象
首先,我们肯定要为类对象建立meta_class的模型,但每个meta_class,应该都能够构建本类的对象,为了实现这一特点,我们想到了模板:
template<typename T>
class MetaClass : public IMetaClass {
public:
virtual void* CreateObject() {
return new T();
}
};
为了让每个类都能有统一的创建方法,我们将使用IMetaClass接口进行多态调用
class IMetaClass {
public:
virtual void* CreateObject() =