2015-07-10 47 views
0

我有这个问题,不知道如何解决它。在C++中创建派生抽象类的实例

假设我有这些基类:

class ValueBase 
{ 
    private: 
    int base_value; 

    public: 
    int GetValue(); 
    void SetValue(int val); 
    virtual ValueBase* Meet(ValueBase* const a, ValueBase* const b) = 0; 
} 

class NodeBase 
{ 
    private: 
    ValueBase* base_nodeValue; 

    public: 
    bool AddValue(int val); 
} 

和派生类:

class Value : public ValueBase 
{ 
    public: 
    Value* Meet(ValueBase* a, ValueBase* b) override; 
} 

有没有办法在方法AddValueNodeBase类创建Value类的实例?我知道我应该可以制作纯虚拟的AddValue,并在NodeBase的派生类中实现它,但有没有可能在没有此选项的情况下执行此操作?我可以使用例如模板方法或可能回调方法Value将构建该对象?或者这样做太邪恶了吗?

编辑: 我没有在NodeBase

+9

'bool AddValue(int val){base_nodeValue = new Value; '繁荣,完成。 –

+0

对,我错过了一个捕获,请参阅编辑。 – benderto

+2

难道你不能正向声明'Value',或者包含正确的头文件以便在'NodeBase'中使用它吗? – BlackDwarf

回答

1

我没有看到没有改变类定义的方法。然而,有许多方法涉及到更改类定义,这取决于您“允许”使用的内容。

答。AddValue()模板对象上键入它应该创建:

// might need to adapt syntax 
class NodeBase 
{ 
    private: 
    ValueBase* base_nodeValue; 

    public: 
    bool AddValue(int val, ValueBase* (*creator)()) { base_nodeValue = (*creator)(); } 
} 

... 
// other code that has access to Value 
ValueBase* valueCreator() { return new Value; } 
... 
node.AddValue(10, valueCreator); 

class NodeBase 
{ 
    private: 
    ValueBase* base_nodeValue; 

    public: 
    template<class ValueType> 
    bool AddValue(int val) { base_nodeValue = new ValueType; } 
} 

... 
// other code that has access to Value 
node.AddValue<Value>(10); 

B.创建一个用于创建Value功能(如果需要的话) and pass it as an argument to AddValue`转发任何参数构造器(也可以在这里使用函子或lambda)

C.你可以在中创建一个函数返回Value*

class ValueBase 
{ 
    public: 
    static ValueBase* createValue(); 
}; 

class NodeBase 
{ 
    private: 
    ValueBase* base_nodeValue; 

    public: 
    bool AddValue(int val) { base_nodeValue = ValueBase::createValue(); } 
}; 

// in a separate cpp 
ValueBase* ValueBase::createValue() { return new Value; } 

这实际上类似于一个工厂的方法:你可以有createValue()接受一个参数并建立不同ValueBase小号取决于它。有ValueBase存储一些指向创建者函数的指针,你可以根本不知道Value,只是在其他地方初始化该指针,就像你可以在基类的工厂表中注册一个子类一样。

+0

谢谢你,对我来说真的很棒:)我结束了模板方法,并用了一些'static_assert'它工作得很好 – benderto

5

访问派生类Value添加创建成员函数:

class ValueBase 
{ 
public: 
    virtual ValueBase * create() = 0; 
    // ... 
}; 

然后在NodeBase你可以使用base_nodeValue->create()

派生类实现:

class Value : public ValueBase 
{ 
    Value * create() override { return new Value; } 
}; 

此模式的更常见的形式是一个克隆功能,不过,其不产生相同类型的默认构造对象,而是一个拷贝

Derived * clone() override { return new Derived(*this); } 
+3

这并不能解决任何问题。采用这种方法,您需要一个正确派生类型的对象,以便创建正确派生类型的对象。 OP显然希望创建一个没有一个。 – JSF

+0

@JSF:OP可以访问一个基址指针,但不是? –

+0

@KerrekSB,它可能是NULL或任何,因为我读的问题 – Petr