[C++学习笔记14]动态创建对象(定义静态方法实现在map查找具体类名对应的创建函数,并返回函数指针,map真是一个万能类)good
[C++学习笔记14]动态创建对象
- C#/Java中的反射机制
动态获取类型信息(方法与属性)
动态创建对象
动态调用对象的方法
动态操作对象的属性
前提:需要给每个类添加元数据
- 动态创建对象
实现原理:通过定义一个宏REGISTER_CLASS,传入类名,在该宏中创建一个类独有的Register类,类中定义静态方法创建对象(new)并返回指针,并在该类中定义一个公共Register类的成员变量,在该公共Register类的构造函数中调用工厂类的Register方法注册类名与创建对象的函数指针到map,在工厂类中定义静态方法实现在map查找具体类名对应的创建函数,并返回调用即可。
#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 nullptr; return it->second();
} 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_; 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); #endif // __DYN_BASE_H__
复制代码 复制代码
#ifndef __SHAPE_H__
#define __SHAPE_H__ #include <iostream>
#include <vector>
#include <string>
using namespace std; class Shape {
public:
virtual void Draw() = ;
virtual ~Shape() {}
}; class Circle : public Shape {
public:
void Draw();
~Circle();
}; class Rectangle : public Shape {
public:
void Draw();
~Rectangle();
}; class Square : public Shape {
public:
void Draw();
~Square();
}; #endif // __SHAPE_H__
复制代码 复制代码
#include "Shape.h"
#include "DynBase.h" 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)
{
//Shape s; // Error, 抽象类不能实例化对象
vector<Shape *> v;
Shape *ps = NULL; 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); // 未将Shape基类的析构函数声明为虚函数之前,并不会调用各个派生类的析构函数
// 声明为虚函数之后,就会调用了
return ;
}
复制代码 复制代码
#include "Shape.h"
#include "DynBase.h" void Circle::Draw()
{
cout << "Circle Draw ... " << endl;
} Circle::~Circle()
{
cout << "~Circle ... " << endl;
} void Rectangle::Draw()
{
cout << "Rectangle Draw .." << endl;
} Rectangle::~Rectangle()
{
cout << "~Rectangle ... " << endl;
} void Square::Draw()
{
cout << "Square Draw ..." << endl;
} Square::~Square()
{
cout << "~Square ... " << endl;
} REGISTER_CLASS(Circle)
REGISTER_CLASS(Square)
REGISTER_CLASS(Rectangle)
http://www.cnblogs.com/ifpelset/articles/4544750.html
[C++学习笔记14]动态创建对象(定义静态方法实现在map查找具体类名对应的创建函数,并返回函数指针,map真是一个万能类)good的更多相关文章
- Mybatis学习笔记14 - 动态sql之foreach标签
一.查询给定集合中员工id对应的所有员工信息 示例代码: 接口定义: package com.mybatis.dao; import com.mybatis.bean.Employee; import ...
- 【转】 C#学习笔记14——Trace、Debug和TraceSource的使用以及日志设计
[转] C#学习笔记14——Trace.Debug和TraceSource的使用以及日志设计 Trace.Debug和TraceSource的使用以及日志设计 .NET Framework 命名空 ...
- SQL反模式学习笔记14 关于Null值的使用
目标:辨别并使用Null值 反模式:将Null值作为普通的值,反之亦然 1.在表达式中使用Null: Null值与空字符串是不一样的,Null值参与任何的加.减.乘.除等其他运算,结果都是Null: ...
- MyBatis:学习笔记(4)——动态SQL
MyBatis:学习笔记(4)——动态SQL 如果使用JDBC或者其他框架,很多时候需要你根据需求手动拼装SQL语句,这是一件非常麻烦的事情.MyBatis提供了对SQL语句动态的组装能力,而且他只有 ...
- 并发编程学习笔记(14)----ThreadPoolExecutor(线程池)的使用及原理
1. 概述 1.1 什么是线程池 与jdbc连接池类似,在创建线程池或销毁线程时,会消耗大量的系统资源,因此在java中提出了线程池的概念,预先创建好固定数量的线程,当有任务需要线程去执行时,不用再去 ...
- SpringBoot学习笔记:动态数据源切换
SpringBoot学习笔记:动态数据源切换 数据源 Java的javax.sql.DataSource接口提供了一种处理数据库连接的标准方法.通常,DataSource使用URL和一些凭据来建立数据 ...
- Ext.Net学习笔记14:Ext.Net GridPanel Grouping用法
Ext.Net学习笔记14:Ext.Net GridPanel Grouping用法 Ext.Net GridPanel可以进行Group操作,例如: 如何启用Grouping功能呢?只需要在Grid ...
- Web Service学习笔记:动态调用WebService
原文:Web Service学习笔记:动态调用WebService 多数时候我们通过 "添加 Web 引用..." 创建客户端代理类的方式调用WebService,但在某些情况下我 ...
- golang学习笔记14 golang substring 截取字符串
golang学习笔记14 golang substring 截取字符串golang 没有java那样的substring函数,但支持直接根据 index 截取字符串mystr := "hel ...
随机推荐
- get_slave_status.py
#!/usr/bin/env python#-*- encoding: utf8 -*- import mysql.connectorimport get_mysql_conn_info &qu ...
- PatentTips - Enhanced I/O Performance in a Multi-Processor System Via Interrupt Affinity Schemes
BACKGROUND OF THE INVENTION This relates to Input/Output (I/O) performance in a host system having m ...
- 【24.67%】【codeforces 551C】 GukiZ hates Boxes
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
- JSON序列化自己主动过滤NULL值
使用Newtonsoft.Json.dll 序列化为json时主动将NULL值过滤掉.详细做法: var jSetting = new JsonSerializerSettings {NullValu ...
- 最简单的基于FFmpeg的AVUtil样例 (AVLog, AVOption等)
本文的演示样例程序记录了FFmpeg的libavutil中几种工具函数的用法: AVLog:日志输出AVOption (AVClass):选项设置AVDictionary:键值对存储ParseUtil ...
- WP8.1开发:简单的天气预报应用
今天小梦给大家分享一个简单的天气预报应用源码:调用的是百度API.整个应用都没有什么难点.只是一个简单的网络请求和json数据处理.在WP8.1有小娜的情况下,天气预报应用还有意义吗?我认为还是有点意 ...
- [Angular] Pluck value from Observable
export class MailFolderComponent implements OnInit{ title: Observable<string>; messages: Obser ...
- MVC4中AJAX Html页面打开调用后台方法实现动态载入数据库中的数据
之前一直用window.onload方法来调用js方法来实现,今天纠结能不能换个方法实现. 非常明显是能够的. 在html前台页面引用js代码例如以下 @Scripts.Render("~/ ...
- USACO--2.1The Castle
思路:这个题目难在建图,開始的时候我想把每一个房间没有墙的面求出来,然后再和他邻近的房间加上一条边进行建图,后面发现要通过题目给定的条件求出房间那个面没有墙是十分困难的:后面參考了别人的思路,我们记录 ...
- 使用JSONP解决跨域问题-代码示例
前段时间用JSONP解决了跨域问题,现在不用了,把代码思路记下来,今后说不定还用得上. JS代码 //查询公告数据 function recentpost(){ $.getJSON(cmsUrl+&q ...