2016-02-25 170 views
0

我正在編寫一個模塊化的軟件,我正在解決接口和內存方面的一些問題。向下轉換const std :: list <const unique_ptr <Base>>

我有一個Base類與關聯和組成一些繁重的工作,所以我寧願寫它在接口一次。問題是要避免任何內存泄漏或問題,只有我的基類應該能夠看到字段。除Base之外的其他人都不應修改mFields列表或釋放其包含的指針。

問題是BaseField將衍生和方法將被添加和我誰將會使用Derived方法程序應直接獲得DerivedField名單:

class BaseField {} ; 
class DerivedField : public BaseField {} ; 

class Base { 
protected: 
    unique_ptr<BaseField> & addField(unique_ptr<BaseField> f) ; 
    const unique_ptr<BaseField> & something() ; 
    const unique_ptr<BaseField> & something2() ; 
    const std::list<const unique_ptr<BaseField>> & getFields() ; 
private: 
    std::list<const unique_ptr<BaseField>> mFields ; 
} 

class Derived : public Base { 
public: 
    unique_ptr<DerivedField> & addField(params) ; 
    const unique_ptr<DerivedField> & something() ; 
    const unique_ptr<DerivedField> & something2() ; 
    const std::list<const unique_ptr<DerivedField>> & getFields() ; 
} 

所以我的問題是如何獲得 const std::list<const unique_ptr<DerivedField>> &Derived::getFields()Base::getFields()

編輯:

我想我沒有清楚地解釋我的問題。我明白了什麼是@NicolBolas說,我agreee他,但並沒有真正幫助我讓我們提出這樣的說法:

我的軟件應該解決不同的問題類型,如Problem1Problem2Problem3

事實是放入系統的所有問題,具有完全相同相同的子結構,如SubProblem1SubProblem2SubProblem3
因此,爲了避免重複代碼,我決定寫一個BaseProblem類和BaseSubProblems誰將會參閱下文爲每一個問題(如addSubProblem(BaseSubProblem *))的結構和COMON操作。
因爲受保護的構造函數(它只是提供避免代碼重複的結構),所以基本問題不是可實現的。另外,addSubProblem(SubProblem *)法保護的,所以只有derivedProblem可以因爲誰創建Problem1知道所有包含在Problem1子問題是SubProblem1類型,每個用戶的增加SubProblem

所以其實我在BaseProblem使用std::list<SubProblem *>和我derived Problem class給出了std::list<SubProblem1 *> Problems1::getSubProblems()
訪問,我想能夠聲明只BaseProblem擁有SubProbblems即使只有derived Problems知道真正的類型的

我希望這個解釋比以前更好。

+1

這不是一個答案,但你應該使用'std :: list >'而不是'std :: list >''。我也想知道你爲什麼要返回'const unique_ptr &'而不是'T *'。 – Simple

+0

事實是,我真的不希望任何人都可以接受我的DerivedField的所有權。我100%確定所有'BaseField'都是'DerivedField'。 –

回答

0

你不能那樣做。事實上,你不能實現的任何你的Derived界面。 C++不會那樣工作。

類型unique_ptr<Derived>unique_ptr<Base>是完全不相關的類型,只要C++是concerend。您不能將一個類型的值,指針或引用轉換或轉換爲另一個類型。那麼,你可以用指針/引用,但你會得到未定義的行爲。 std::list<T>也是如此。

你的問題是你似乎想通過引用unique_ptr左右。這是一個糟糕的API。如果有人採取unique_ptr,那麼這應該意味着他們是該對象的claiming ownership。通過傳遞unique_ptraddField,呼叫者告訴Base接受該指針的所有權。因爲它返回對該指針的引用違反了unique_ptr的獨特所有權概念。

addField和它的同義詞應該只是返回裸指針:Base*等等。使用裸指針,沒有所有權影響。

至於getFields ......好吧,你將不得不拿出基於對暴露這樣一份名單裸指針的API。也許你應該在內部有一個vector<Base*>你可以公開,或者你可以創建一個圍繞list的迭代器的迭代器封裝,它從unique_ptr中提取指針。

還應當指出的是,你使用這個人造壓倒一切的語法,其中派生類隱藏基類成員函數與使用其自身的指針版本,一般較差OOP風格。它需要太多的「downcasting」,這是危險的,我建議。沒有什麼能阻止用戶在基類中發送非DerivedaddFields的東西,並且該類的用戶本身不應該關心這種或那種方式。

如果他們必須關心,那麼你是在做OOP錯誤。

+0

我忘了頂寫基地和派生之間的關係。其實我是用裸指針來做的,但我試着通過閱讀Bjarne Stroustrup書來提高我的C++水平。所以我決定清楚地告訴我只有我的Base類擁有這些字段,但是使用Derived類的用戶並不關心Base類。 –

+0

@ QuentinHuot-Marchand:您的澄清不會改變任何內容。您仍然不應該返回對'unique_ptr'或對包含它們的容器的引用。如果'Derived'的用戶不應該關心'Base',那麼你仍然在使用OOP錯誤。 –

相關問題