博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++动态创建类的实例
阅读量:4363 次
发布时间:2019-06-07

本文共 4228 字,大约阅读时间需要 14 分钟。

写在前面:首先声明,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  5 #include 
6 7 typedef void* (*NewInstancePt)(); 8 9 class CObjectFactory10 {11 public:12 static void* CreateObject(const char *className)13 {14 std::map
::const_iterator it;15 it = dynCreateMap.find(className);16 if(it == dynCreateMap.end())17 return NULL;18 else19 {20 NewInstancePt np = it->second;21 return np();22 }23 }24 25 static void RegisterClass(const char *className, NewInstancePt np)26 {27 dynCreateMap[className] = np;28 }29 private:30 static std::map
dynCreateMap;31 };32 33 std::map
CObjectFactory::dynCreateMap;34 35 class Register36 {37 public:38 Register(const char *className, NewInstancePt np)39 {40 CObjectFactory::RegisterClass(className, np);41 }42 };43 44 #define REGISTER_CLASS(class_name) \45 class class_name##Register \46 { \47 public: \48 static void* NewInstance() \49 { \50 return new class_name(); \51 } \52 private: \53 static Register reg; \54 }; \55 Register class_name##Register::reg(#class_name, class_name##Register::NewInstance)56 57 #endif //__C_OBJECT_FACTORY_H_

最后,当然还有如何使用的主函数内容。

RTTI.cpp

1 #include 
2 #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就会知道原来动态加载如此容易。。。

 

转载于:https://www.cnblogs.com/asworld/p/4045214.html

你可能感兴趣的文章
windows命令——explorer
查看>>
<转载>Bootstrap 入门教程 http://www.cnblogs.com/ventlam/archive/2012/05/28/2520703.html 系列...
查看>>
jquery和js cookie的使用解析
查看>>
类的内置方法
查看>>
世界是数字的 读后感
查看>>
算法项目步骤流程
查看>>
POJ 2942 Knights of the Round Table ★(点双连通分量+二分图判定)
查看>>
10.scheam.xml的配置
查看>>
通过命令给Linux(CentOS)分区
查看>>
python接口自动化3-自动发帖(session)
查看>>
复杂问题的简单抽象:魔兽世界中的兔子们
查看>>
那些美到极致的语言!
查看>>
Xamarin的不归路-ios模拟器没有键盘
查看>>
【云笔记】群晖DS218+ NoteStation 折腾
查看>>
jdk安装配置
查看>>
四、RocketMq简单的消费者和生产者(示例代码)
查看>>
json介绍
查看>>
Maven编译unmappable character for encoding Cp1252问题
查看>>
xftp上传文件失败,执行程序发现磁盘满了:No space left on device
查看>>
duplicate symbols for architecture i386 问题?
查看>>