根据类名动态创建类

hyp3388191 2011-12-11 12:31:09
目标:
输入一个类名,如果这个类名存在,就创建该类的一个实例,否则,什么也不做。

#include "stdafx.h"
#include <afx.h>
#include <iostream>
#include <string>
using namespace std;

class A
{
public:
A()
{
cout<<"A class create !"<<endl;
}
};

class B
{
public:
B()
{
cout<<"B class create !"<<endl;
}
};

//
void* Create(string& classname)
{ //这里怎么实现?或者有更好解决方法?
void* pMyclass;
CRuntimeClass* pclass = RUNTIME_CLASS(classname);//这里报错。
pMyclass = pclass->CreateObject();
return pMyclass;
}

//工厂模式,缺点是如果增加另一个类C,必须修改工厂代码。
//目标是当添加一个新类时,不用修改原有代码,所以该方法弃而不用。
void* FactoryCreate(string &classname)
{
void* pMyClass = NULL;

if (classname == "A")
pMyClass = new A;
else if (classname == "B")
pMyClass = new B;
// else if (classname == "C") 新增加一个类C必须添加这一条件分支
// pMyClass = new C;
else
pMyClass = NULL;

return pMyClass;
}

int _tmain(int argc, _TCHAR* argv[])
{
string str;

cin>>str;
A *pA = (A*)Create(str);
delete pA;

cin>>str;
B *pB = (B*)Create(str);
delete pB;

system("pause");
return 0;
}
...全文
247 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]
来个纯C++的,不要宏的。

C/C++ code

#include <map>
#include <iostream>
#include <string>

class factory
{
struct abs_generator
{
virtual ~abs_generator(){}
virtual void * constructor……
[/Quote]

我调用的时候,为什么报错? 错误时这样的:error C2062: type 'int' unexpected
fjwzyy 2011-12-13
  • 打赏
  • 举报
回复
3楼的下面这两行代码没有问题吗

//创建
int * p = f.make("int");
std::string * str = f.make("string");

f.make("xx")出来的是一个对象, 而现在编译器将尝试将对象转换为对象的指针, 我想编译器应该有报错吧.
Jinhao 2011-12-13
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 fjwzyy 的回复:]

3楼的下面这两行代码没有问题吗

//创建
int * p = f.make("int");
std::string * str = f.make("string");

f.make("xx")出来的是一个对象, 而现在编译器将尝试将对象转换为对象的指针, 我想编译器应该有报错吧.
[/Quote]

不会有问题. f::make创建一个obj_wrapper对象, 而obj_wrapper提供一个转换函数模板
template<typename T> operator T*();
所以 int * p = f.make("int"); 这个语句 会产生一个obj_wrapper对象,然后它的转换函数检测到往int指针转换。然后转换的时候,需要判断make的类型是不是int。如果是,就会得到int指针。否则得到空指针。
PointertoPointer 2011-12-11
  • 打赏
  • 举报
回复
候俊杰<深入浅出MFC>第三章,有个控制台程序.模仿动态创建,你看看
Jinhao 2011-12-11
  • 打赏
  • 举报
回复
另外,还有类型检查,可以带来一点点的安全性。例如
int * p = f.make("string");
factory知道,string对象不能由int*引用,因此factory就决定不创建这个string对象,p也就是空指针。
hyp3388191 2011-12-11
  • 打赏
  • 举报
回复
灰常好,再等一会,如果没有更好的方法,分就归你了(我所有的分都给你了,T_T)
mstlq 2011-12-11
  • 打赏
  • 举报
回复
google"工厂模式" 楼主应该可以得到不少启发,呵呵
Jinhao 2011-12-11
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 hyp3388191 的回复:]

3楼好猛,必须要用模板吗?
[/Quote]

可以不用呀,但是麻烦。
比如,你的创建方法,每次添加一个新的类就要修改该方法。多麻烦,你看我的,每次添加一个类,只需要用material这个方法告诉factory就可以了,你可以在任何地方用该方法告诉factory,而不必修改factory的代码
hyp3388191 2011-12-11
  • 打赏
  • 举报
回复
说错了,是2楼
hyp3388191 2011-12-11
  • 打赏
  • 举报
回复
3楼好猛,必须要用模板吗?
羽飞 2011-12-11
  • 打赏
  • 举报
回复
RUNTIME_CLASS貌似是MFC中的,可以用typeid
Jinhao 2011-12-11
  • 打赏
  • 举报
回复
来个纯C++的,不要宏的。


#include <map>
#include <iostream>
#include <string>

class factory
{
struct abs_generator
{
virtual ~abs_generator(){}
virtual void * constructor() = 0;
};

template<typename T>
struct generator: abs_generator
{
void * constructor()
{
return (new T());
}
};

struct obj_wrapper
{
obj_wrapper(abs_generator* ag)
: abs_gen_(ag)
{}

template<typename T>
operator T*()
{
return (dynamic_cast<generator<T>*>(abs_gen_) ?
reinterpret_cast<T*>(abs_gen_->constructor()) : 0);
}
private:
abs_generator * abs_gen_;
};
public:
~factory()
{
for(std::map<std::string, abs_generator*>::iterator i = genmap_.begin(); i != genmap_.end(); ++i)
{
delete i->second;
}
}

template<typename T>
void material(const std::string& str)
{
std::map<std::string, abs_generator*>::iterator i = genmap_.find(str);
if(i == genmap_.end())
genmap_[str] = new generator<T>;
}

obj_wrapper make(const std::string& str)
{
std::map<std::string, abs_generator*>::iterator i = genmap_.find(str);
return obj_wrapper(i != genmap_.end() ? i->second : 0);
}
private:
std::map<std::string, abs_generator*> genmap_;
};

int main()
{
factory f;
//首先设置可以创建类型
f.material<int>("int");
f.material<std::string>("string");

//创建
int * p = f.make("int");
std::string * str = f.make("string");

cout<<*p<<endl;
cout<<*str<<endl;
}
主要特性Java 语言是简单的:Java 语言的语法与 C 语言和 C++ 语言很接近,使得大多数程序员很容易学习和使用。另一方面,Java 丢弃了 C++ 中很少使用的、很难理解的、令人迷惑的那些特性,如操作符重载、多继承、自动的强制型转换。特别地,Java 语言不使用指针,而是引用。并提供了自动分配和回收内存空间,使得程序员不必为内存管理而担忧。Java 语言是面向对象的:Java 语言提供、接口和继承等面向对象的特性,为了简单起见,只支持之间的单继承,但支持接口之间的多继承,并支持与接口之间的实现机制(关键字为 implements)。Java 语言全面支持动态绑定,而 C++语言只对虚函数使用动态绑定。总之,Java语言是一个纯的面向对象程序设计语言。Java语言是分布式的:Java 语言支持 Internet 应用的开发,在基本的 Java 应用编程接口中有一个网络应用编程接口(java net),它提供了用于网络应用编程的库,包括 URL、URLConnection、Socket、ServerSocket 等。Java 的 RMI(远程方法激活)机制也是开发分布式应用的重要手段。Java 语言是健壮的:Java 的强型机制、异常处理、垃圾的自动收集等是 Java 程序健壮性的重要保证。对指针的丢弃是 Java 的明智选择。Java 的安全检查机制使得 Java 更具健壮性。Java语言是安全的:Java通常被用在网络环境中,为此,Java 提供了一个安全机制以防恶意代码的攻击。除了Java 语言具有的许多安全特性以外,Java 对通过网络下载的具有一个安全防范机制( ClassLoader),如分配不同的名字空间以防替代本地的同名、字节代码检查,并提供安全管理机制( SecurityManager)让 Java 应用设置安全哨兵。Java 语言是体系结构中立的:Java 程序(后缀为 java 的文件)在 Java 平台上被编译为体系结构中立的字节码格式(后缀为 class 的文件),然后可以在实现这个 Java 平台的任何系统中运行。这种途径适合于异构的网络环境和软件的分发。Java 语言是可移植的:这种可移植性来源于体系结构中立性,另外,Java 还严格规定了各个基本数据型的长度。Java 系统本身也具有很强的可移植性,Java 编译器是用 Java 实现的,Java 的运行环境是用 ANSI C 实现的。Java 语言是解释型的:如前所述,Java 程序在 Java 平台上被编译为字节码格式,然后可以在实现这个 Java 平台的任何系统中运行。在运行时,Java 平台中的 Java 解释器对这些字节码进行解释执行,执行过程中需要的在联接阶段被载入到运行环境中。Java 是高性能的:与那些解释型的高级脚本语言相比,Java 的确是高性能的。事实上,Java 的运行速度随着 JIT(Just-In-Time)编译器技术的发展越来越接近于 C++。Java 语言是多线程的:在 Java 语言中,线程是一种特殊的对象,它必须由 Thread 或其子(孙)来创建。通常有两种方法来创建线程:其一,使用型构为 Thread(Runnable) 的构造子将一个实现了 Runnable 接口的对象包装成一个线程,其二,从 Thread 派生出子并重写 run 方法,使用该子创建的对象即为线程。值得注意的是 Thread 已经实现了 Runnable 接口,因此,任何一个线程均有它的 run 方法,而 run 方法中包含了线程所要运行的代码。线程的活动由一组方法来控制。Java 语言支持多个线程的同时执行,并提供多线程之间的同步机制(关键字为 synchronized)。Java 语言是动态的:Java 语言的设计目标之一是适应于动态变化的环境。Java 程序需要的能够动态地被载入到运行环境,也可以通过网络来载入所需要的。这也有利于软件的升级。另外,Java 中的有一个运行时刻的表示,能进行运行时刻的型检查。

64,648

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧