返回带有抽象类的 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<Engine>
时试图返回对std::unique_ptr<IEngine>
的引用。由于类型不同,此处不会发生自动转换。此外,在这种情况下,我也不认为返回对 unique_ptr 的引用是一个好主意。
unique_ptr<Engine> != unique_ptr<IEngine>
所以你不能只绑定对它的引用(从 Get 返回)
Get()
应该做什么?所有权转让?只允许(无限制)访问类中的对象(有点打破封装)
【参考方案1】:
std::unique_ptr<IEngine>
是与std::unique_ptr<Engine>
不同的类型,因此您要求返回对临时对象的引用。
std::unique_ptr
唯一拥有它指向的对象,因此即使您删除了引用,从您可能想要的现有 std::unique_ptr<Engine>
创建 std::unique_ptr<IEngine>
也是不正确的保持不变。
你不应该在这里暴露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的主要内容,如果未能解决你的问题,请参考以下文章