返回带有抽象类的 unique_ptr

Posted

技术标签:

【中文标题】返回带有抽象类的 unique_ptr【英文标题】:Return unique_ptr with abstract class inside 【发布时间】:2021-09-23 13:30:36 【问题描述】:

我正在尝试封装引擎实现类的细节。为此,我返回抽象类的std::unique_ptr(在我的情况下为IEngine)而不是Engine。但由于编译错误,我无法做到这一点。我可以返回原始参考并且它可以工作,但是unique_ptr 可以吗?提前致谢。

class IEngine

public:
    virtual ~IEngine() = default;

    virtual void Start() = 0;
;

class Engine : public IEngine

public:
    void Start() override 
;

class Car

    std::unique_ptr<Engine> m_engine;

public:

    std::unique_ptr<IEngine>& Get()  return m_engine;  // Here is compile error
;

int main()

    Car lambo;


【问题讨论】:

注意:总是添加你的错误信息 将成员设为私有但从 Get 返回非 const 引用的目的是什么? 如果没有错误消息,我猜这个问题是在指针为std::unique_ptr&lt;Engine&gt; 时试图返回对std::unique_ptr&lt;IEngine&gt; 的引用。由于类型不同,此处不会发生自动转换。此外,在这种情况下,我也不认为返回对 unique_ptr 的引用是一个好主意。 unique_ptr&lt;Engine&gt; != unique_ptr&lt;IEngine&gt; 所以你不能只绑定对它的引用(从 Get 返回) Get() 应该做什么?所有权转让?只允许(无限制)访问类中的对象(有点打破封装) 【参考方案1】:

std::unique_ptr&lt;IEngine&gt; 是与std::unique_ptr&lt;Engine&gt; 不同的类型,因此您要求返回对临时对象的引用。

std::unique_ptr 唯一拥有它指向的对象,因此即使您删除了引用,从您可能想要的现有 std::unique_ptr&lt;Engine&gt; 创建 std::unique_ptr&lt;IEngine&gt; 也是不正确的保持不变。

你不应该在这里暴露std::unique_ptr。我不确定您是否应该在这里公开IEngine。我也很困惑为什么您需要在Car 中输入具体的Engine,但外部世界需要可变访问指向IEngine 的指针。

我希望得到类似的东西:

class Car

    std::unique_ptr<IEngine> m_engine;

public:

    void TurnIgnition()  m_engine->Start(); 
;

【讨论】:

【参考方案2】:

我正在尝试封装引擎实现类的细节。

返回对私有成员的非常量引用很少是正确的做法。无论如何,它与数据封装相反。一旦调用者获得了参考,他们就可以随心所欲地使用它。返回非 const 引用对于方便访问方法(例如 std::vector::operator[])是有意义的。 std::vector::operator[] 的目的不是向调用者隐藏元素。还有其他方法可以得到它。而是std::vector::operator[] 是为了更方便地访问元素。不是封装。

也不清楚为什么要从Get 返回unique_ptr。当不需要所有权转移时,不需要返回智能指针。

我可以返回原始参考

是的,很好:

#include <memory>

class IEngine

public:
    virtual ~IEngine() = default;

    virtual void Start() = 0;
;

class Engine : public IEngine

public:
    void Start() override 
;

class Car

    std::unique_ptr<Engine> m_engine;

public:

    const IEngine& Get()  return *m_engine;  // Here is compile error
;

int main()

    Car lambo;

【讨论】:

以上是关于返回带有抽象类的 unique_ptr的主要内容,如果未能解决你的问题,请参考以下文章

带有抽象类的 Python ctypes

带有案例类的抽象类的scala circe编码器/解码器

抽象类的 shared_ptr 向量到副本向量

Django:从带有元的抽象类的多重继承

使用带有某些基类、抽象类或特征的列表参数化的类型类的最佳方法

JAVA抽象类的定义与使用