在运行时分配指向多态类的指针

时间:2016-01-06 14:08:58

标签: c++ inheritance polymorphism

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 ...

3 个答案:

答案 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*()> >

不同之处在于负责将回调添加到地图的代码是定义派生类的位置。