向下转换const std :: list <const unique_ptr <base =“”>&gt;

时间:2016-02-25 14:18:38

标签: c++ c++11

我正在编写一个模块化软件,我正在解决接口和内存方面的一些问题。

我有一个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()?{/ p>

编辑:

我想我没有清楚地解释我的问题。我理解@NicolBolas在说什么,我同意他的意见,但并不能真正帮助我,所以让我们这样说:

我的软件应解决不同的问题类型,例如Problem1 Problem2Problem3

事实是所有问题都有完全相同的子问题结构,例如SubProblem1 SubProblem2 SubProblem3
因此,为了避免代码重复,我决定编写一个BaseProblem类和一个BaseSubProblems,它将为每个问题(例如addSubProblem(BaseSubProblem *))重复结构和comon操作。 基本问题不是可实现的,因为受保护的构造函数(它只是为避免代码重复而提供的结构)。 addSubProblem(SubProblem *)方法也受到保护,因此只有derived Problem可以添加SubProblem
因此,创建Problem1的每个用户都知道Problem1中包含的所有SubProblem都是SubProblem1的类型。

实际上,我在std::list<SubProblem *>中使用BaseProblemderived Problem class通过std::list<SubProblem1 *> Problems1::getSubProblems()提供访问权限 我希望能够宣布只有BaseProblem只有SubProbblems拥有derived Problems,即使只有SubProblems知道gridview的实际类型

我希望这种解释比前一种更好。

1 个答案:

答案 0 :(得分:0)

你不能这样做。实际上,您无法像这样实现<{1}}接口的任何。 C ++不会那样工作。

类型Derivedunique_ptr<Derived>是完全不相关的类型,只要C ++是可以理解的。您不能将一种类型的值,指针或引用转换或转换为另一种类型。好吧,你可以用指针/引用,但你会得到未定义的行为。 unique_ptr<Base>也是如此。

您的问题是您似乎想要将引用传递给std::list<T>。这是一个糟糕的API。如果有人选择unique_ptr,那么这应该意味着他们是该对象的unique_ptr。通过将claiming ownership传递给unique_ptr,调用者告诉addField获取该指针的所有权。对于它返回对该指针的引用是违反Base的唯一所有权概念。

unique_ptr及其同类应返回裸指针:addField等。使用裸指针,没有所有权影响。

至于Base* ......好吧,你将不得不想出一个基于裸指针的API来公开这样的列表。也许你应该在内部有一个可以公开的getFields,或者你可以在vector<Base*>的迭代器周围创建一个迭代器包装器,它从list中提取指针。

还应该注意,您使用的这种虚假覆盖语法,派生类将基类成员函数隐藏在使用自己的指针的版本中,通常是糟糕的OOP样式。它需要过多的&#34;向下转换&#34;,这是危险的,并且是建议的。没有什么可以阻止用户在基类中发送不是unique_ptr的{​​{1}}内容,并且该类用户本身不应该关心这种方式。< / p>

如果他们必须关心,那么你做错了OOP。