A类包含一个指向抽象类B的指针(只实现了头文件):
// A.h
#include "B.h"
class A {
public:
A();
virtual ~A();
pointBto(B* b_); // { this.b = b_; }
private:
B* b;
}
// B.h
class B {
public:
B();
virtual ~B();
virtual void b_method() = 0;
}
C类和D类继承B。
// C.h
#include "B.h"
Class C : public B {
public:
C();
~C();
virtual b_method();
}
// D.h
#include "B.h"
Class D : public B {
public:
D();
~D();
virtual b_method();
}
应用程序读取一个字符串,并根据该字符串创建一个C或D类的新对象,并将b指向创建的对象。
注意:我不想创建一个无穷无尽的链
if (string_ == "C")
{
a_.pointBto(new C());
}
else if (string_ == "D")
{
a_.pointBto(new D());
}
else ...
答案 0 :(得分:1)
只需创建一个std::map<std::string, std::function<B*(/*...*/)>>
:
static const std::map<std::string, std::function<B*(/*...*/)>> factory = {
{ "C", [](/*...*/){ return new C(/*...*/); },
{ "D", [](/*...*/){ return new D(/*...*/); },
};
a_.pointBto(factory[string_](/*arguments*/));
答案 1 :(得分:1)
您所寻找的内容通常被称为“虚拟构造函数”。我通常不是这个结构的粉丝,但它可以使用例如'clone'idiom来实现。如下所示:
struct Parent {
virtual Parent* clone(/*??? arg*/) = 0;
};
struct Child1 : Parent {
/*virtual */ Parent clone(/*??? arg*/) { return new Child1(/*arg*/); }
};
/* Child 2 */
Parent* make_parent(Choice arg) {
static std::map<Choice, Parent*> factory({{ch1, new Child1()}, {ch2, new Child2()}};
return factory.find(arg).second->clone(/**/);
}
最大的问题是clone
参数被简化为某种blob,这需要强制转换。
答案 2 :(得分:1)
如果您希望避免在每次添加新派生类时都扩展if else块(或其他类似的集中式机制),则可以让派生类型自行注册。
检查此主题是否有关于如何操作的技巧:
Is there a way to instantiate objects from a string holding their class name?
(请注意,根据给出的解决方案,字符串不必与类名相同)。基本上你还有一个从字符串到工厂函数的映射,即
map< std::string, std::function<B*()> >
不同之处在于负责将回调添加到地图的代码是定义派生类的位置。