2015-07-10 71 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