C++动态创建类的实例

写在前面:首先声明,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 <map>
 5 #include <string>
 6
 7 typedef void* (*NewInstancePt)();
 8
 9 class CObjectFactory
10 {
11 public:
12     static void* CreateObject(const char *className)
13     {
14         std::map<std::string, NewInstancePt>::const_iterator it;
15         it = dynCreateMap.find(className);
16         if(it == dynCreateMap.end())
17             return NULL;
18         else
19         {
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<std::string, NewInstancePt> dynCreateMap;
31 };
32
33 std::map<std::string, NewInstancePt> CObjectFactory::dynCreateMap;
34
35 class Register
36 {
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 <stdio.h>
 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<CObject *>(CObjectFactory::CreateObject("CObjectA"));
10     std::string className;
11     if(objA == NULL)
12     {
13         printf("[ERROR] Can‘t Create Class ObjectA!\n");
14     }
15     else
16     {
17         className = objA->GetClassName();
18         printf("[OK] Create %s !\n", className.c_str());
19     }
20
21     CObject *objB = static_cast<CObject *>(CObjectFactory::CreateObject("CObjectB"));
22     if(objB == NULL)
23     {
24         printf("[ERROR] Can‘t Create Class ObjectB!\n");
25     }
26     else
27     {
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就会知道原来动态加载如此容易。。。

时间: 2024-08-25 18:19:32

C++动态创建类的实例的相关文章

C# Activator.CreateInstance 动态创建类的实例(二)

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Kernel.Interface { public interface IObjcet { void Put(); void Put(string plus); } } using System; using System.Collections.

C# Activator.CreateInstance 动态创建类的实例(一)

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Kernel.SimpleLibrary { public class Person { private string name; public Person(){ } public Person(string name) { this.name

Python中动态创建类实例

Python中动态创建类实例 简介 在Java中我们可以通过反射来根据类名创建类实例,那么在Python我们怎么实现类似功能呢? 其实在Python有一个builtin函数import,我们可以使用这个函数来在运行时动态加载一些模块.如下: def createInstance(module_name, class_name, *args, **kwargs): module_meta = __import__(module_name, globals(), locals(), [class_n

[译文]运行时利用反射动态地创建类的实例

介绍 通常我们使用类的名称创建一个实例/类的对象,例如,如果我有一个名为 User 的类,我们会去这样创建这个类. 1 User UR = new User(); 2 UR.ID = 1; 3 UR.Name = "Kailash"; 但如果有人你在让你在应用程序运行时或者通过字符串作为类名创建一个类的实例,你将如何做? 别担心,微软.Net 框架提供了一种解决方案. 在System.Reflection名称空间的 Assembly类和System名字空间的和Activator 类可以

C# 利用反射根据类名创建类的实例对象

“反射”其实就是利用程序集的元数据信息. 反射可以有很多方法,编写程序时请先导入 System.Reflection 命名空间. 1.假设你要反射一个 DLL 中的类,并且没有引用它(即未知的类型): Assembly assembly = Assembly.LoadFile("程序集路径,不能是相对路径"); // 加载程序集(EXE 或 DLL) object obj = assembly.CreateInstance("类的完全限定名(即包括命名空间)");

python动态创建类的声明

动态创建类的声明 使用内置函数type,原型:class type(name, bases, dict)name是类的名字,相当于__class__bases是类的基类,元组,可以有多个基类,但是基类必须直接或者间接继承自object类,否则会报错dict是类的变量,字典类型,相当于静态变量,与在__init__函数中声明的不同 代码示意片段: class A(object): def __init__(self): print "A init ..." class B(A): def

设计模式之工厂模式:模拟DECLARE_DYNAMIC和IMPLEMENT_DYNAMIC动态创建类对象

该形式的工厂模式是我项目中用到的方法,属于很成熟的模版,读者可以直接拿来在自己项目中使用.个人感觉这种方法真正做到了"开放封闭"的原则,最大好处是用户产品类的设计完全不依赖于该模式的实现,比如提供必须的相关函数等.如果不理解工厂模式的话,请参考网上其它文章,本实现在理解上有一点小小的难度.好东西,大家慢慢享用,话不多说,先放代码! 首先是产品基类,它相当于一个接口,产品需要有什么动作就写在这里吧! #ifndef _CPRODUCTBASE_H_ #define _CPRODUCTBA

通过字符串动态创建类对象

功能的需求是  不需要使用IOC 框架 来对创建指定对象. .NET 中  要想动态的 创建对象   做耦合  好像只能做到 将类生成DLL 后  然后 加载DLL 接着创建对象. JAVA 当个类文件 就可以运行. 希望做到  当读一个   .class  或者 .TXT 就可以  动态创建类对象  那多好啊!!! 还可以将 类文件 以字符串的形式写到 数据库中  通过数据库来 创建类对象. 然后就各种百度 谷歌 贴吧等  找有没相关的 解决方案    还好  找到了  . 不藏着 分享出来

C#根据类名称创建类的实例

转:http://blog.csdn.net/ise_keven1/article/details/2070049 方案一: using   System;       using   System.Reflection; Type   type   =   Type.GetType("abc");     Activator.CreateInstance(type); 方案二: using   System;       using   System.Reflection;