写在前面:首先声明,C++实际上是不可以动态创建类的实例的。
下面简单做一个解释,所谓动态创建类的实例是指在程序运行过程中创建并使用一个“未知”的类。而“未知”是指在程序编译时并不知道有哪些类是需要动态创建的。对于C++这门语言来说,编译时不知道的类是不可以在运行时使用的。所以我说C++是不可以的。
不过C++可以做到另一件事情,基本可以满足大多数类似的需求。
我描述为通过类名称创建类的实例。
进入正题。
首先描述一下需求:
编写一个程序实现在程序运行过程中通过类名称(即字符串变量)创建该类的实例,且在主程序中不出现该类的声明。
然后进行分析设计:
1.在主程序中不出现类的声明,还需要用这个类。那很自然就会想到用基类指针实现。
2.创建一个指向该类的基类指针,则需要使用new运算符。
3.通过类名调用相应的new运算符,则需要使用map加函数指针。
4.最后,如何在主函数执行之前构造该map,则需要用到静态成员在主函数运行前进行创建的机制。
下面给出代码实现:
首先有一个CObject类作为基类,由它派生出CObjectA和CObjectB两个需要动态创建的子类。
Object.h
1 #ifndef __C_OBJECT_H_ 2 #define __C_OBJECT_H_ 3 4 #include "ObjectFactory.h" 5 6 class CObject 7 { 8 public: 9 CObject(): className("CObject") {}10 virtual ~CObject(){}11 virtual const std::string GetClassName()12 {13 return className;14 }15 private:16 std::string className;17 };18 19 #endif //__C_OBJECT_H_
ObjectA.h
1 #ifndef __C_OBJECT_A_H_ 2 #define __C_OBJECT_A_H_ 3 4 #include "Object.h" 5 6 class CObjectA : public CObject 7 { 8 public: 9 CObjectA(): className("CObjectA") {}10 ~CObjectA(){}11 const std::string GetClassName()12 {13 return className;14 }15 private:16 std::string className;17 };18 19 REGISTER_CLASS(CObjectA);20 21 #endif //__C_OBJECT_A_H_
ObjectB.h
1 #ifndef __C_OBJECT_B_H_ 2 #define __C_OBJECT_B_H_ 3 4 #include "Object.h" 5 6 class CObjectB : public CObject 7 { 8 public: 9 CObjectB(): className("CObjectB") {}10 ~CObjectB(){}11 const std::string GetClassName()12 {13 return className;14 }15 private:16 std::string className;17 };18 19 REGISTER_CLASS(CObjectB);20 21 #endif //__C_OBJECT_B_H_
然后重点就来了,上面两个类里面都有的宏定义REGISTER_CLASS。实际上就是声明一个带有静态成员的注册类,通过初始化该静态成员实现构造动态创建map。
ObjectFactory.h
1 #ifndef __C_OBJECT_FACTORY_H_ 2 #define __C_OBJECT_FACTORY_H_ 3 4 #include
最后,当然还有如何使用的主函数内容。
RTTI.cpp
1 #include2 #include "ObjectFactory.h" 3 #include "Object.h" 4 #include "ObjectA.h" 5 #include "ObjectB.h" 6 7 int main(int argc, const char *argv[]) 8 { 9 CObject *objA = static_cast (CObjectFactory::CreateObject("CObjectA"));10 std::string className;11 if(objA == NULL)12 {13 printf("[ERROR] Can't Create Class ObjectA!\n");14 }15 else16 {17 className = objA->GetClassName();18 printf("[OK] Create %s !\n", className.c_str());19 }20 21 CObject *objB = static_cast (CObjectFactory::CreateObject("CObjectB"));22 if(objB == NULL)23 {24 printf("[ERROR] Can't Create Class ObjectB!\n");25 }26 else27 {28 className = objB->GetClassName();29 printf("[OK] Create %s !\n", className.c_str());30 }31 32 return 0;33 }
这样就完成了所谓的动态创建。这里需要注意的是在主函数所在的文件里面需要include所有的需要动态创建的类,否则的话在编译的过程中这些类以及其注册类就根本不会被编译,也就不会构建动态创建map,整个机制也就失效了。这也就是我说的C++实际上是不可以动态创建类的原因。
不得不说,如果想要彻底的动态创建,建议使用Java。简单看看Java的反射机制和ClassLoader就会知道原来动态加载如此容易。。。