C++对象动态生成(Dynamic Create)的简单实现
2012-05-11 17:17
561 查看
以前一直是C++的coder,最近由于到了另一家公司,因此开始写java项目,相信C++的程序员都会对java语言原生支持的动态生成很是羡慕,但是C++不支持反射(reflection),也就无法根据类名动态创建对象,MFC的做法是继承CObject并用DECLARE_DYNCREATE宏来实现,MFC这么实现是由于一些系统遗留问题,感觉用起来不是那么的friendly。今天下午坐着无聊,仿造java的结构构思了下C++的动态生成实现方法。
基本想法:
1.java的所有类都默认继承自Object类,在C++中我们也需要这么一个公用的基类。
2.java中每个类都有对应的一个Class类,用来动态创建类对象,我们也定义一个Class类
3.java中可以用Class.forName(String className)来获得相应的Class类,我们的Class类也应该支持这种方式
4.java中用Class.newInstance()动态生成类的实例,其实Class类在这里就相当于一个Factory,我们也提供这种方式
基本上,只要实现了上述4个条件,类的动态创建就跟java的方式差不多了,具体代码如下:
核心代码:
Class.h
Class.cpp
用户类:这里为了演示的需要定义了两个用户类
Example.h
Example1.h
Example1.cpp
How to Use:
output
这样c++就就基本实现了java的动态生成机制,相比java来说,我们继承Object的同时还需要调用Class::Register函数注册一下,上面对于Class对象的示例代码中是直接比较指针地址,用户也可以重写Class对象的operator==来根据Class的name是否相等进行比较。另外一个缺陷是无法判断一个类是否是一个类的子类实例,比如我再写一个类SubExample继承Example,但目前是无法判断一个SubExample是否是一个Example的,如果需要做到这点,可以保存整个类的继承关系图,就是Class初始化的时候再加一个父类型参数,然后把整个继承关系保存下来。可以参见完善版本:C++对象动态生成(Dynamic
Create)的完善版本
-------------------------------------------------------------我是分割线--------------------------------------------------------------
对于zhouguidi 提出的模板类的动态创建问题,可能不只一个网友会遇到,这里贴出一些可能的实现思路和代码。由于C++模板类的实现机理是一个类定义应用于多个类,只有当用户指定具体的类型之后,类定义才真正完整,也就是说一个模板类可以生成无穷个类。对于动态创建模板类对象来说,我们不可能把这些无穷个类都进行注册,因此有以下两种解决方案:
1.穷举法:对于所有用到的模板类,在程序开始的某一段代码里面进行穷举注册
Class::Register<TemplateExample<int>>("TemplateExample<int>");
Class::Register<TemplateExample<float>>("TemplateExample<float>");
Class::Register<TemplateExample<double>>("TemplateExample<double>");
……
然后后续代码就可以通过Class::forName("TemplateExample<int>")等来获得对应模板类的Class对象,这种方法比较容易理解,也比较通用,不管类型参数是基本类型还是自定义类型都可以使用,但代码有点冗余繁琐。
2.自动注册:该方法的好处是不需要再写很多重复的Register语句,但需要对模板类的类型参数有一定的约定,因此只能应用于模板类的类型参数是自定义类型的情况,具体见代码
TemplateExample.h
TemplateExample.cpp
How to Use:
output
今天重新跑了下该示例程序,发现还存在一个似乎跟编译器相关的问题,如果整个代码中都没有引用到某个类的theClass变量,那么该变量是不会初始化的,也就是Class::Register函数不会被调用,该类也就没有注册。因此我在TemplateExample的初始化函数中用了一下theClass->getName()来输出类的名字,以确保会初始化该变量,我用的是elipse的g++编译器(按我原来的理解,既然类生产了,必然会初始化类的静态成员,但实际不是,只有真正代码中使用到过才会初始化该静态成员变量,这应该是g++编译器的一个优化,不知道别的编译器会不会也做同样的处理)
基本想法:
1.java的所有类都默认继承自Object类,在C++中我们也需要这么一个公用的基类。
2.java中每个类都有对应的一个Class类,用来动态创建类对象,我们也定义一个Class类
3.java中可以用Class.forName(String className)来获得相应的Class类,我们的Class类也应该支持这种方式
4.java中用Class.newInstance()动态生成类的实例,其实Class类在这里就相当于一个Factory,我们也提供这种方式
基本上,只要实现了上述4个条件,类的动态创建就跟java的方式差不多了,具体代码如下:
核心代码:
Class.h
/* * C++对象动态创建(Dynamic Create)简单实现 *使用方法:对每一个需要动态创建的类,继承自Object类,并调用Class::Register<Class>(className)注册一下即可 * Created on: 2012-5-11 * Author: torytin */ #ifndef CLASS_H_ #define CLASS_H_ #include <map> #include <string> using namespace std; /** * Object类,需要动态生成的类都必须继承该类 * 目前该类无任何功能,只是一个标记 * @author torytin */ class Class; class Object { public: //用来保存创建的Class类 static const Class *const theClass; }; /** * 对象工厂模板类,该类用来生成具体的对象 * @author torytin * */ template<class T> class ObjectFactory { public: static Object *create() { return new T(); } ; }; /** * Class类,用来存储类信息 * 为了可以把具体的类型对用户隐藏,Class类没有设成模板类 * 因为C++的模板类对象持有的时候必须指定具体的类名,如果设定为模板类 * 使用的时候只能是Class<类名> *pClass,而不能是Class *pClass。 * 用户还是需要知道具体类名,就失去了动态创建的意义,但为了达到动态创建的目的, * Class类的Register是一个template函数,具体的类型信息,需要用户在注册类的时候提供 * @author torytin * */ class Class { private: //创建对象的函数指针定义 Object *(*factory)(void); //用来存储当前注册的所有可动态创建的Class static map<string, Class*> classMap; //类的名称 string name; //Class类不允许外部初始化 Class() { } public: /*** * Class类注册函数,该注册函数是template函数。 * 用户需要提供T的具体类型和类的唯一标识符(一般为类名),比如生成Example类的Class: * Class::Register<Example>("Example"); * 参数: * T:具体的类 * className:注册的名字(一般为类名,也可以为任意字符) */ template<class T> static Class * Register(string className) { if (classMap.count(className)==0) { Class *cls = new Class(); cls->factory = &ObjectFactory<T>::create; //函数指针赋值,根据T的类型赋值相应的创建函数 cls->name = className; //类名的唯一标识符 classMap[className] = cls; //在这里注册该class类 } return classMap[className]; } ; //根据类的名字获得类对应的Class static Class *forName(string className); //生成类的实例 Object *newInstance() const; //获得类名 string getName() const; virtual ~Class(); }; #endif /* CLASS_H_ */
Class.cpp
/* * Class.cpp * * Created on: 2012-5-11 * Author: torytin */ #include "Class.h" map<string, Class*> Class::classMap=map<string, Class*>(); string Class::getName() const{ return name; } Class *Class::forName(string className) { if (classMap.count(className) != 0) { return classMap[className]; } return NULL; } Object *Class::newInstance() const { return factory(); } Class::~Class() { } //注册Object类信息,在这里,我们把返回的Class类存放在theClass中,方便后续使用 const Class *const Object::theClass = Class::Register<Object>("Object");
用户类:这里为了演示的需要定义了两个用户类
Example.h
/* * C++动态创建类示例 * 对象必须继承Object类,并且必须有一个无参的构造函数 * 定义对象后需要调用Class::Register函数注册当前类,可以把生成的Class保存在static变量中供后续使用 * Created on: 2012-5-11 * Author: torytin */ #ifndef EXAMPLE_H_ #define EXAMPLE_H_ #include "Class.h" class Example: public Object{ public: //用来保存创建的Class类,这里保存只是为了方便使用,不是强制要求 static const Class * theClass; Example(); virtual ~Example(); }; #endif /* EXAMPLE_H_ */Example.cpp
/* * Example.cpp * * Created on: 2012-5-11 * Author: torytin */ #include <iostream> #include "Example.h" Example::Example() { std::cout<<"Example is initialized"<<endl; } Example::~Example() { } //注册Example类信息,在这里,我们把返回的Class类存放在theClass中,方便后续使用 const Class * Example::theClass = Class::Register<Example>("Example");
Example1.h
/* * Example1.h * * Created on: 2012-5-13 * Author: torytin */ #ifndef EXAMPLE1_H_ #define EXAMPLE1_H_ #include "Class.h" class Example1: public Object { public: static const Class * theClass; Example1(); virtual ~Example1(); }; #endif /* EXAMPLE1_H_ */
Example1.cpp
/* * Example1.cpp * * Created on: 2012-5-13 * Author: torytin */ #include <iostream> #include "Example1.h" Example1::Example1() { std::cout<<"Example1 is initialized"; } Example1::~Example1() { // TODO Auto-generated destructor stub } //注册Example1类 const Class * Example1::theClass = Class::Register<Example1>("Example1");
How to Use:
//============================================================================ // Name : dynamic.cpp // Author : torytin // Version : // Copyright : // Description :Object dynamic create in C++, Ansi-style //============================================================================ #include <iostream> #include "Example.h" using namespace std; void createExample(Class *cls){ if(cls==Example::theClass){ cout<<"it's a Example Class"<<endl; cls->newInstance(); }else{ cout<<"it's not a Example Class"<<endl; } } int main() { createExample(Class::forName("Example")); createExample(Class::forName("Example1")); return 0; }
output
it's a Example Class Example is initialized it's not a Example Class
这样c++就就基本实现了java的动态生成机制,相比java来说,我们继承Object的同时还需要调用Class::Register函数注册一下,上面对于Class对象的示例代码中是直接比较指针地址,用户也可以重写Class对象的operator==来根据Class的name是否相等进行比较。另外一个缺陷是无法判断一个类是否是一个类的子类实例,比如我再写一个类SubExample继承Example,但目前是无法判断一个SubExample是否是一个Example的,如果需要做到这点,可以保存整个类的继承关系图,就是Class初始化的时候再加一个父类型参数,然后把整个继承关系保存下来。可以参见完善版本:C++对象动态生成(Dynamic
Create)的完善版本
-------------------------------------------------------------我是分割线--------------------------------------------------------------
对于zhouguidi 提出的模板类的动态创建问题,可能不只一个网友会遇到,这里贴出一些可能的实现思路和代码。由于C++模板类的实现机理是一个类定义应用于多个类,只有当用户指定具体的类型之后,类定义才真正完整,也就是说一个模板类可以生成无穷个类。对于动态创建模板类对象来说,我们不可能把这些无穷个类都进行注册,因此有以下两种解决方案:
1.穷举法:对于所有用到的模板类,在程序开始的某一段代码里面进行穷举注册
Class::Register<TemplateExample<int>>("TemplateExample<int>");
Class::Register<TemplateExample<float>>("TemplateExample<float>");
Class::Register<TemplateExample<double>>("TemplateExample<double>");
……
然后后续代码就可以通过Class::forName("TemplateExample<int>")等来获得对应模板类的Class对象,这种方法比较容易理解,也比较通用,不管类型参数是基本类型还是自定义类型都可以使用,但代码有点冗余繁琐。
2.自动注册:该方法的好处是不需要再写很多重复的Register语句,但需要对模板类的类型参数有一定的约定,因此只能应用于模板类的类型参数是自定义类型的情况,具体见代码
TemplateExample.h
/* * TemplateExample.h * * Created on: 2012-11-27 * Author: Torytin */ #ifndef TEMPLATEEXAMPLE_H_ #define TEMPLATEEXAMPLE_H_ #include "Class.h" template <class T> class TemplateExample: public Object { public: //用来保存创建的Class类,这里保存只是为了方便使用,不是强制要求 static const Class * theClass; TemplateExample(); virtual ~TemplateExample(); }; #endif /* TEMPLATEEXAMPLE_H_ */
TemplateExample.cpp
/* * TemplateExample.cpp * * Created on: 2012-11-27 * Author: Torytin */ #include <iostream> #include "TemplateExample.h" template <class T> TemplateExample<T>::TemplateExample() { std::cout<<theClass->getName()+" is initialized"<<endl; } template <class T> TemplateExample<T>::~TemplateExample() { // TODO Auto-generated destructor stub } //注册该模板类信息,在这里,要求模板参数T也是属于可以动态创建的对象,且有一个theClass的静态变量指向该类的Class对象 //也可以对T只要求实现某一个方法获得一个可以表述该类名字的唯一字符串,比如要求T实现T::getClassName() template <class T> const Class * TemplateExample<T>::theClass = Class::Register<TemplateExample<T> >("TemplateExample<"+T::theClass->getName()+">");
How to Use:
//============================================================================ // Name : templateTest.cpp // Author : torytin // Version : // Copyright : // Description :template Object dynamic create in C++, Ansi-style //============================================================================ #include <iostream> #include "Example.h" #include "Example1.h" //注意这里是引入模板类的实现文件,因为对于模板类,使用前是需要知道类的完整定义的 #include "TemplateExample.cpp" using namespace std; void createTemplateExample(const Class *cls){ if(cls==TemplateExample<Example>::theClass){ cout<<"it's a TemplateExample<Example> Class,instance it"<<endl; cls->newInstance(); }else{ cout<<"it's not a TemplateExample<Example> Class"<<endl; } } int main() { //这里可以成功的通过类名字获得类的Class对象,前提是代码中必须出现过TemplateExample<Example1>(出现位置无所谓) createTemplateExample(Class::forName("TemplateExample<Example1>")); //代码中必须出现过TemplateExample<Example1>,这里只是让它出现那么一下 new TemplateExample<Example1>(); //这里可以直接用Class::forName方法获得TemplateExample<Example>的类对象,是因为createTemplateExample函数代码中出现过该类 createTemplateExample(Class::forName("TemplateExample<Example>")); return 0; }
output
TemplateExample is initialized it's not a TemplateExample<Example> Class it's a TemplateExample<Example> Class,instance it TemplateExample is initialized
今天重新跑了下该示例程序,发现还存在一个似乎跟编译器相关的问题,如果整个代码中都没有引用到某个类的theClass变量,那么该变量是不会初始化的,也就是Class::Register函数不会被调用,该类也就没有注册。因此我在TemplateExample的初始化函数中用了一下theClass->getName()来输出类的名字,以确保会初始化该变量,我用的是elipse的g++编译器(按我原来的理解,既然类生产了,必然会初始化类的静态成员,但实际不是,只有真正代码中使用到过才会初始化该静态成员变量,这应该是g++编译器的一个优化,不知道别的编译器会不会也做同样的处理)
相关文章推荐
- C++对象动态生成(Dynamic Create)的简单实现
- C++对象动态生成(Dynamic Create)的完善版本
- 【cocos2d-x】C++利用类名动态生成对象,类似于Objective-C Class *aclass = [object class]
- C++模板实现动态顺序表(更深层次的深浅拷贝)与基于顺序表的简单栈的实现
- 利用Java反射机制和Javassist实现Java对象及其属性的动态创建生成
- C#:简单实现动态数据生成Word文档并保存
- C++实现根据类名动态生成类对象
- C++如何实现类对象只能动态分配或只能静态分配
- C++ 类工厂实现动态对象创建
- [C++学习笔记14]动态创建对象(定义静态方法实现在map查找具体类名对应的创建函数,并返回函数指针,map真是一个万能类)good
- c++动态加载dll中的类(用于实现依据字符串类名创建对象)
- C++初学初练类与对象之矩阵简单功能实现
- C#简单实现动态数据生成Word文档并保存
- 利用hadoop命令rcc生成Record 一种简单的方式实现自定义的writable对象
- 从零开始学C++之模板(四):用模板实现单例模式(线程安全)、模板方式实现动态创建对象
- C#:简单实现动态数据生成Word文档并保存
- C++对象布局及多态实现之动态和强制转换
- C++如何动态的生成对象详解
- C++实现动态分配const对象实例
- C++实现动态顺序表(类和对象)