C++ 动态创建对象
转自:http://www.cnblogs.com/jisi5789/p/3190353.html
回顾前面的文章,实现了一个简单工厂模式来创建不同类对象,但由于c++没有类似new "Circle"之类的语法,导致CreateShape 函
数中需要不断地ifelse地去判断,如果有多个不同类对象需要创建,显然这是很费神的,下面通过宏定义注册的方法来实现动态创
建对象。
Shape.h:
#ifndef _SHAPE_H_
#define _SHAPE_H_ class Shape
{
public:
virtual void Draw() = ;
virtual ~Shape() {}
}; class Circle : public Shape
{
public:
void Draw();
~Circle();
}; class Square : public Shape
{
public:
void Draw();
~Square();
}; class Rectangle : public Shape
{
public:
void Draw();
~Rectangle();
}; #endif // _SHAPE_H_
Shape.cpp:
#include "Shape.h"
#include "DynBase.h"
#include <iostream>
using namespace std; void Circle::Draw()
{
cout << "Circle::Draw() ..." << endl;
}
Circle::~Circle()
{
cout << "~Circle ..." << endl;
} void Square::Draw()
{
cout << "Square::Draw() ..." << endl;
}
Square::~Square()
{
cout << "~Square ..." << endl;
} void Rectangle::Draw()
{
cout << "Rectangle::Draw() ..." << endl;
} Rectangle::~Rectangle()
{
cout << "~Rectangle ..." << endl;
} REGISTER_CLASS(Circle);
REGISTER_CLASS(Square);
REGISTER_CLASS(Rectangle);
DynBase.h:
#ifndef _DYN_BASE_H_
#define _DYN_BASE_H_ #include <map>
#include <string>
using namespace std; typedef void *(*CREATE_FUNC)(); class DynObjectFactory
{
public:
static void *CreateObject( const string &name)
{
map<string, CREATE_FUNC>::const_iterator it;
it = mapCls_.find(name);
if (it == mapCls_.end())
return ;
else
return it->second(); //func(); } static void Register( const string &name, CREATE_FUNC func)
{
mapCls_[name] = func;
}
private:
static map<string, CREATE_FUNC> mapCls_;
}; // g++
// __attribute ((weak))
__declspec(selectany) map<string, CREATE_FUNC> DynObjectFactory::mapCls_;
//头文件被包含多次,也只定义一次mapCls_; class Register
{
public:
Register( const string &name, CREATE_FUNC func)
{
DynObjectFactory::Register(name, func);
}
}; #define REGISTER_CLASS(class_name) \
class class_name##Register { \
public: \
static void* NewInstance() \
{ \
return new class_name; \
} \
private: \
static Register reg_; \
}; \
Register class_name##Register::reg_(#class_name, class_name##Register::NewInstance)
//CircleRegister #endif // _DYN_BASE_H_
DynTest.cpp:
#include "Shape.h"
#include "DynBase.h"
#include <iostream>
#include <vector>
#include <string>
using namespace std; void DrawAllShapes( const vector<Shape *> &v)
{
vector<Shape *>::const_iterator it;
for (it = v.begin(); it != v.end(); ++it)
{
(*it)->Draw();
}
} void DeleteAllShapes( const vector<Shape *> &v)
{
vector<Shape *>::const_iterator it;
for (it = v.begin(); it != v.end(); ++it)
{
delete(*it);
}
} int main( void)
{
vector<Shape *> v; Shape *ps;
ps = static_cast<Shape *>(DynObjectFactory::CreateObject( "Circle"));
v.push_back(ps);
ps = static_cast<Shape *>(DynObjectFactory::CreateObject( "Square"));
v.push_back(ps);
ps = static_cast<Shape *>(DynObjectFactory::CreateObject( "Rectangle"));
v.push_back(ps); DrawAllShapes(v);
DeleteAllShapes(v); return ;
}

在DynBase.h 中#define了一个宏定义REGISTER_CLASS(class_name),且在Shape.cpp 中调用宏定义,拿REGISTER_CLASS(Circle);
来说,程序编译预处理阶段会被替换成:
class CircleRegister {
public:
static void* NewInstance()
{
return newCircle;
}
private:
static Register reg_;
};
Register CircleRegister::reg_("Circle",CircleRegister::NewInstance);
也即定义了一个新类,且由于含有static 成员,则在main函数执行前先执行初始化,调用Register类构造函数,在构造函数中调用
DynObjectFactory::Register(name, func); 即调用DynObjectFactory 类的静态成员函数,在Register函数中通过map容器完成了
字符串与函数指针配对的注册,如mapCls_[name] = func;
进入main函数,调用DynObjectFactory::CreateObject("Circle") ,CreateObject函数中通过string找到对应的函数指针
(NewInstance),并且调用后返回创建的对象指针,需要注意的是 return it->second(); 中it->second 是函数指针,后面加括
号表示调用这个函数。对宏定义中的#,##用法不熟悉的可以参考这里。
这样当需要创建多个不同类对象的时候,就不再需要写很多ifelse的判断了。
参考:
C++ primer 第四版
Effective C++ 3rd
C++编程规范
C++ 动态创建对象的更多相关文章
- C# 中反射获取某类的子类和根据类型名动态创建对象
有时候,为了快速批量处理已经实现某个基类或者某个接口的子类,需要通过反射的方式获取到他们的类类型(Type),然后再通过 1 Activator.CreateInstance(objType); 或者 ...
- swift如何动态创建对象
前言: 在一些大型的项目中常常在加载页面的时候根据服务器请求下来的数据动态创建视图控制器对象,最近的一个项目就有这一方面的需求,加载页面之前需要先请求服务器的数据得到一个JSON字典,根据里面字符串的 ...
- C#主要支持 5 种动态创建对象的方式
C#主要支持 5 种动态创建对象的方式: 1. Type.InvokeMember 2. ContructorInfo.Invoke 3. Activator.CreateInstance(Type) ...
- 于Unity3D动态创建对象和创建Prefab三种方式的原型对象
于Unity3D动态创建对象和创建Prefab三种方式的原型对象 u3d在动态创建的对象,需要使用prefab 和创建时 MonoBehaviour.Instantiate( GameObject o ...
- C# 利用反射动态创建对象——带参数的构造函数和String类型
C# 利用反射动态创建对象——带参数的构造函数和String类型 最近笔者有一个想法需要利用反射动态创建对象(如string,int,float,bool,以及自定义类等)来实现,一直感觉反射用不好, ...
- 使用hql动态创建对象问题
前段时间由于需求要添加报表数据,调整ireport后,打印pdf文件出现数据错位的情况,调试发现不是ireport问题,就查看了后台传送的数据,最后发现传送的对象属性值已经就是错位的,那就是获取对象时 ...
- MFC中关于运行时类信息及动态创建对象的两个宏的意义(转)
http://blog.csdn.net/ligand/article/details/49839507 MFC运行时类信息 用途: 程序在运行时,获取对象类的信息及类的继承关系 实现: 1.定义的类 ...
- C#利用反射动态创建对象 带参数的构造函数和String类型 (转载)
最近笔者有一个想法需要利用反射动态创建对象(如string,int,float,bool,以及自定义类等)来实现,一直感觉反射用不好,特别是当构造函数带参数的时候.MSDN上给出的例子十分复杂,网上的 ...
- C# 利用反射动态创建对象[摘录]
摘自:http://hi.baidu.com/yangyuhang/blog/item/f12ea90e13f214e336d12250.html 在VS.Net中,有很多种方法动态调用对象的构造函数 ...
- protobuf在java应用中通过反射动态创建对象(DynamicMessage)
---恢复内容开始--- 最近编写一个游戏用到protobuf数据格式进行前后台传输,苦于protobuf接受客户端的数据时是需要数据类型的如xxx.parseForm(...),这样就要求服务器在接 ...
随机推荐
- I.MX6 show battery states in commandLine
#/bin/sh # I.MX6 show battery states in commandLine # 声明: # 在命令行下自动显示电池状态的信息. # # -- # set battery r ...
- Java [Leetcode 338]Counting Bits
题目描述: Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculat ...
- 修改dbwr后台进程数量
批量执行脚本时,批量数据写回到数据库:从EM中查看到有较多的dbwr的IO请求 查看后台dbwr的进程数量 select * from v$bgprocess 在查询结果中paddr的字段为非'0 ...
- mysql优化小技巧
对mysql优化时一个综合性的技术,主要包括 a: 表的设计合理化(符合3NF) b: 添加适当索引(index) [四种: 普通索引.主键索引.唯一索引unique.全文索引] c: 分表技术(水平 ...
- cgroup的测试数据
[root@xxxx /cgroup/memory/rule3021]#cat memory.limit_in_bytes503316480 480M [root@xxxx /cgroup/mem ...
- bjfu1109 最小公倍数和
这题真是过了n年才a.最早是在2010年北大培训比赛上看到的这题,当时我不会,竹教主也不会,但他记下来了,研究一段时间后就会了,还把这题加到我校oj上.过了这么多年,我上网搜,关于这个问题的解题报告还 ...
- PHP Module中获取$_GET/$_POST/$_COOKIE的方法研究
假设要获取$_GET['c']; 首先,先介绍下http_globals; 1.http_globals,定义在php_globals.h中: zval * http_globals[6]; 其中的索 ...
- C++小游戏:扑克牌21点
21点扑克牌游戏: 程序说明:该程序是模拟21点扑克牌游戏,玩家最多可以要5张牌,但是如果牌的点数之和超过21点,则自动出局,在不超过21点的情况下,玩家与庄家比牌的大小,大者为赢家 程序片段分析: ...
- springmvc基础知识
springmvc框架,类似于struts,主要用于MVC的控制层 spring的简单配置(非注解): spring-mvc.xml文件(springMVC框架的基本文件) web.xml文件 ja ...
- jedis连接池详解(Redis)
转自:http://tianxingzhe.blog.51cto.com/3390077/1684306 原子性(atomicity): 一个事务是一个不可分割的最小工作单位,事务中包括的诸操作要么都 ...