将unique_ptr用作抽象基类中的私有成员

Using a unique_ptr as a private member in an abstract base class

本文关键字:成员 基类 抽象 unique ptr      更新时间:2023-10-16

我对C++相当陌生(但不是C或OOP(,但我试图以"正确"的方式做事,避免任何不良和/或危险的习惯,所以我使用Google的C++编码指南和有效C++作为我学习的起点。

我有一个抽象基类,其中unique_ptr作为成员。如果我将其设为私有并且仅通过 getter 提供对派生类的访问(根据 Google C++ 样式指南(,这是最好的方法吗?还是我在这里错过了一个潜在的陷阱?

基数:

#include "Document.h"
typedef std::unique_ptr<Document> pDOC;
class Base {
public:
    Base();
    virtual ~Base() = 0;
    pDOC& GetDoc();
private:
    // Unique pointers cannot be shared, so don't allow copying
    Base(Base const &); // not supported
    Base &operator=(Base const &); // not supported
    pDOC m_doc;
};

基地.cpp

#include "base.h"
Base::Base()
: m_xmldoc(new Document) {}
// Class destructor (no need to delete m_doc since it is a smart pointer)
Base::~Base() {}
pDOC& Base::GetDoc() {
    return m_doc;
}

首先,称它为upDoc而不是pDOC - unique_ptr足够奇怪,以至于您需要一些指示该类型不仅仅是一个指针。 (将指针类型定义为以小写 p 开头的趋势很强,因此很多人可能会对您的使用感到困惑(。

其次,GetDoc如果它仅用于派生类,则应protected而不是public

第三,我质疑是否完全向所有孩子公开提及unique_ptrBase的责任是什么? 它是否管理m_doc的生命周期? 如果是这样,请公开Document*而不是upDoc(return m_doc.get();而不是return m_doc;(

如果Base所做的只是持有一个m_doc而不管理其生命周期,那么它为什么存在? 它不提供公共接口,并且几乎不提供任何功能。

如果我将其设为私有并且仅通过 getter 提供对派生类的访问

然后,您正在执行额外的键入,以获得与直接提供公共/受保护成员相同的效果。诚然,您可以向访问器添加代码,并且可以设置断点,但这不会改变通过提供对内部的直接访问来破坏封装的事实。

换句话说,没有什么可以阻止该类型的用户执行obj.GetDoc().release()并破坏您可能对类型具有的不变量。

另一种选择是公开对std::unique_ptr管理的对象的引用,例如:

    const Document& getDocument() const { return *m_doc; }
    Document& getMutableDocument() { return *m_doc; }

Jonas Devlieghere在这里建议将其作为公开"唯一指针容器"的可能方法,因为他认为"[b]返回引用而不是指针,你清楚地表明调用者不负责管理[指向对象]的生命周期。