2016-02-25 118 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错误。 –

相关问题