双11狂欢大促

盲盒赢 定制羽绒服

开启惊喜盲盒,抽取你的专属好礼

— 惊喜奖品抢先看 —

[多态]用输入的名字来生成子类的对象

cxjddd cxjddd 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区
第一次写多态的程序,遇到一个问题,就是输入一个类名字,怎样方便地 new 出一个子类的对象。
  假设基类是 base,子类有 A,B。
  开始我是这样的:
if (name == base::class_name())
p = new base;
else if (name == A::class_name())
p = new A;
else if (name == B::class_name())
p = new B;
else
p = 0;
  我觉得这样不好,不容易维护,想添加新的子类的话,要改的地方很多,而且容易漏掉。

  于是我就想有一个“管理器”来给我管理就好了,我只要在最开始的时候向管理器注册一下,以后用名字就可以方便地从管理器里分配一个新的对象了。
  初步想的话,每个类应该有两个 static 成员函数,一个用来给出类的名字,另一个则用于分配一个对象。
  可以写出基类如下:
class base
{
public:
~base ();
static const char* class_name ()
{
static const char _name[]="base";
return _name;
}
static base* alloc () { return new base; }
};
  这样,每个类都有一对 class_name 和 alloc,查到 class_name 后就可以通过 alloc 分配一个对象。

  下面是管理器的代码:
template <class base_t>
class poly_alloc
{
typedef base_t* value_type;
typedef value_type (*alloc_type)();
vector<pair<const char*, alloc_type> > alloces;
public:
void
reg (const char* name, alloc_type a)
{
alloces.push_back (make_pair (name, a));
}

value_type
alloc (const string& name)
{
value_type _new = 0;
for (int i = 0; i < alloces.size(); i++)
if (name == alloces[i].first)
{
_new = (*alloces[i].second)();
break;
}
return _new;
}
};
  用 reg 去注册一个子类(当然也可以是基类),以后用 alloc 就可以分配了。如:
poly_alloc<mybase> pa;
pa.reg (mybase::class_name(), mybase::alloc);
pa.reg (A::class_name(), A::alloc);
pa.reg (B::class_name(), B::alloc);

mybase* p;
p = pa.alloc ("A");
delete p;

整个代码如下:
#include <iostream>
#include <cstdlib>
#include <string>
#include <vector>
#include <utility>
using namespace std;

class mybase
{
public:
virtual ~mybase ()
{}

static mybase*
alloc ()
{
mybase* _new = new mybase;
return _new;
}

virtual const char*
name ()
{
return class_name();
}

static const char*
class_name ()
{
static const char _name[]="base";
return _name;
}

virtual void
foo ()
{
cout << name() << " done" << endl;
}
};

class A: public mybase
{
public:
static mybase*
alloc ()
{
A* _new = new A;
return _new;
}

const char*
name ()
{
return class_name();
}

static const char*
class_name ()
{
static const char _name[]="A";
return _name;
}

void
foo ()
{
cout << name() << " done" << endl;
}
};

class B: public mybase
{
public:
static mybase*
alloc ()
{
B* _new = new B;
return _new;
}

const char*
name ()
{
return class_name();
}
static const char*
class_name ()
{
static const char _name[]="B";
return _name;
}

void
foo ()
{
cout << name() << " done" << endl;
}
};

template <class base_t>
class poly_alloc
{
typedef base_t* value_type;
typedef value_type (*alloc_type)();
vector<pair<const char*, alloc_type> > alloces;
public:
void
reg (const char* name, alloc_type a)
{
alloces.push_back (make_pair (name, a));
}

value_type
alloc (const string& name)
{
value_type _new = 0;
for (int i = 0; i < alloces.size(); i++)
if (name == alloces[i].first)
{
_new = (*alloces[i].second)();
break;
}
return _new;
}
};

int
main ()
{
poly_alloc<mybase> pa;
pa.reg (mybase::class_name(), mybase::alloc);
pa.reg (A::class_name(), A::alloc);
pa.reg (B::class_name(), B::alloc);

mybase* p;

cout << "There are class (base, A, B)" << endl;

string str;
do
{
cout << "Please input a class name:";
cin >> str;
p = pa.alloc (str);
if (p == 0)
break;
p->foo ();
delete p;
}
while (true);

system ("Pause");
return 0;
}
...全文

相关推荐

评论 8
收藏 已收藏
分享
返回顶部
cxjddd
C++ 语言 65,214 成员 250,514 内容