包含该类的标题的Pimpl

时间:2013-09-02 13:00:58

标签: c++ design-patterns pimpl-idiom

我遇到了一个将pimpl类作为标题的实现,并将其包含在pimpl实现中。它甚至有意义吗?像这样:

UI.h

class UI {

public:

   UI();
   virtual ~UI();

   // bunch of methods
private:

      UIImpl* m_impl;
}

UIImpl.h

class UIImpl
{

public:

  UIImpl( ...) ;
  ......
}

UIImpl.cpp

#include "UIImpl.h" 

UIImpl::UIImpl()

{

  //Actual Implementation
  ...

}

我在想PIMPL的原因是将实现完全隐藏在cpp文件中。有一个标题会失败吗?

4 个答案:

答案 0 :(得分:2)

他们是不同类型的标题。 UI.h是“公共的” - 它是库的外部接口的一部分,供其客户使用。

UIImpl.h是“私有的”,就像UIImpl.cpp一样。只要它永远不会包含在公共标题中,它就会对客户端保持不可见,就像.cpp本身一样。

impl类定义拆分为头文件可能有多种原因。也许其他一些实现类传递了UIImpl&个参数。也许只在标题上运行doxygen更容易。也许这只是项目政策。

最重要的是,它仍然是Pimpl,只要你不发布私有标题。

答案 1 :(得分:1)

这样做很有意义。它允许修改UIImpl.h(和相关的.cpp),而无需更改依赖于UI.h的代码。由于UIimpl类仅存储为指针[并且可能UI本身只能访问UIimpl类的公共方法,因此UI.h代码不知道UIimpl类。

事实上,你可能需要“UIimpl.h”来允许UI类看到类的公共功能。

E.g。

class UIImpl
{

public:

     UIImpl( ...) ;
     void func() { ... }
}

class UI 
{

  public:

   UI();
   virtual ~UI();

   // bunch of methods
   void func() { m_impl->func(); }
   ... 
}

要使其正常工作,UI需要知道UIimpl类提供的公共接口。

答案 2 :(得分:1)

  

我在想PIMPL的原因是将实现完全隐藏在cpp文件中。有一个标题会失败吗?

不一定。 pIMPL可用于快速值交换(可能在C ++ 11 /移动语义之前的体系结构中),桥接设计模式或任何其他数量的其他原因。

桥梁设计模式的一个例子:

class WinImpl { virtual ~WinImpl() = 0; /* other interfaces here */ };

// different header file(s)
#ifdef WIN32
class WindowsWinImpl: public WinImpl { /* ... */ };
#else
class LinuxWinImpl: public WinImpl { /* ... */ };
#endif

// different header file
class Window { private: WinImpl* pImpl /*= OSWindowFactory::CreateImpl();*/ };

在这种情况下,你有一个pImpl模型,在WinImpl类的标题中包含Window的定义是完全可以的(因为目的不是为了隐藏实现而是为了抽象这是界面)。

答案 3 :(得分:0)

是的,确实有意义。

使用示例:在为多个操作系统开发的代码中,UI.h可以从与操作系统无关的代码中看到,但不是UIImpl.h。依赖于操作系统的代码(实现代码)将同时看到头文件,UI.h和UIImpl.h