何时在 C++ 中的嵌套类上使用 Pimpl 模式,反之亦然?

Posted

技术标签:

【中文标题】何时在 C++ 中的嵌套类上使用 Pimpl 模式,反之亦然?【英文标题】:When to use Pimpl pattern over Nested class in C++ or vice versa? 【发布时间】:2019-08-01 10:05:23 【问题描述】:

在 C++ 中,大多数开发人员都使用 pimpl idiomopaque pointers 对公共 API 隐藏私有数据/实现,例如:

    => 第一种情况 ## 不透明指针和 PIMPL 成语 ##

//在头文件中

class Node; 
class Graph   
 public:    
  A();  
 private:  
  Node* m_nodeImpl; 

// 类节点将在各自的cpp中定义

2。 =>第二种情况##内部类/嵌套类方法##

//在头文件中

class Graph   
 public:    
  Graph();  
 private:  
  class Node
  
    // implementation goes here
  
  Node* m_nodeImpl;


问题是...

    从类设计的角度来看,这两者之间的实际区别是什么(可能是设计模式)? 每种方法的优缺点是什么?

【问题讨论】:

您可以将两者结合起来,您只需声明 Graph::Node 类,并在源文件中定义。 至于区别,在第二个示例中,人类阅读头文件可以看到Node类的详细信息。 @Someprogrammerdude 我认为这是 pimpl/opaque_ptr 相对于嵌套类 impl 的主要优势,对吧? (甚至隐藏细节) 通常这不是“隐藏”人类的问题,而是依赖问题。 IE。如果Node 的实现(和声明)取决于其他一些类,则需要将其包含在标题中。在 PIML 情况下,您不需要这个。这对于例如不需要公开实现细节的 API 类来说可能很重要。 @sklott 是的,我忘记了这一点,感谢您再次引起我的注意,是的,因此考虑到这两个因素,pimpl 是首选,对吧?那么实际上何时在 C++ 中使用内部类?除了人类可读的东西 【参考方案1】:

你混淆了几件事:

    第一个例子

      Type: opaque - 这意味着类型 name 对该标头的用户可见,但定义是隐藏的。

      当您想与用户共享指针时,不透明类型特别有用,而不是它指向 的详细信息(或者阻止用户摆弄它,或者打破依赖关系)。

      存储:粉刺。这只是意味着用户知道您(可能)在某处有一个 opaque 类型的实例,并且他们知道您的***对象的大小包括该指针。

    第二个例子

      类型:嵌套 - 这样可以避免污染封闭的命名空间(因此在您的程序的同一命名空间中可以有其他类型的 Node,与第一个示例不同)但会暴露所有细节。

      请注意,您的嵌套类型也可以前向声明,以控制可见性和命名空间污染。

      存储:丢失。你是不是也想在这里有一个Node *m_impl?否则,这些示例无法直接进行比较,因为您的 Graph 无处可保留 Node,但是声明了类型。

【讨论】:

感谢您的简短而清晰的描述,Totally forgot to add Node impl ptr on 2nd example,我明白了您的意思。

以上是关于何时在 C++ 中的嵌套类上使用 Pimpl 模式,反之亦然?的主要内容,如果未能解决你的问题,请参考以下文章

使用 std::unique_ptr 的 C++ Pimpl Idiom 不完整类型

实现 pimpl idiom 时出现链接器错误

指向 C++ 中类的指针的 PIMPL 习语

如何在 C++ 中获取抽象(?)pimpl 的调试信息?

C++: The PIMPL idiom

C++ 设计篇之——pimpl 机制