返回带有抽象类的 unique_ptr

问题描述

我正在尝试封装 Engine 实现类的细节。为此,我将返回抽象类的 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;
}

解决方法

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

std::unique_ptr 唯一拥有它指向的对象,因此即使您删除了引用,从现有的 {{1} 创建一个 std::unique_ptr<IEngine> 也是不正确的} 你大概想保持不变。

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

相反,我希望得到类似的结果:

IEngine
,

我正在尝试封装 Engine 实现类的详细信息。

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

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

我可以返回原始引用

是的,那完全没问题:

#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;
}