为什么我们在pimpl中使用'new'?

时间:2016-06-20 13:53:04

标签: c++

我正在研究如何在C ++中使用pimpl,我在教程中找到了这段代码:

// In MyClass.h

class MyClassImp;                    // forward declaration of Pimpl

class MyClass
{
public:
   MyClass ();
   ~MyClass();

   MyClass( const MyClass &rhs );   // undefined for simplicity
   MyClass& operator=( MyClass );

   void  Public_Method();

private:
   MyClassImp *pimpl_;              // the Pimpl
};

// In MyClass.cpp

#include "MyClass.h"

class MyClassImp
{
public:
   void   Private_Method()  {}  // dummy private function

   int    private_var_;            // a private variable
};

MyClass::MyClass()  :  pimpl_( new MyClassImp() )
{
}

MyClass::~MyClass()
{
   delete  pimpl_;
}

void   MyClass::Public_Method()
{
   pimpl_->Private_Method();      // do some private work

   pimpl_->private_var_  = 3;
}

但是我无法理解在堆中分配MyClassImp的原因,我们不能只在堆栈上使用变量吗?

澄清:

如果我们将MyClassImp放在一个单独的.h和.cpp文件中,并在MyClass.h中包含.h,并使用MyClassImp pimpl_; (没有指针),它会不会达到同样的效果?当MyClassImp的实现发生变化时,调用者(MyClass)不需要更改和重新生成。 (他们仍然需要重新链接)

3 个答案:

答案 0 :(得分:5)

pimpl-idiom的技巧是,在你的头文件中只使用一个指针。这意味着您可以使用类的前向声明,而无需实际提供声明。

因此,您可能稍后更改您的声明(在cpp中),而不会使用标题影响标题或其他编译单元。

这在处理库时特别有用。

答案 1 :(得分:1)

由于指针,你需要做一个新的事情。指针存在,因此您可以转发声明(即不包括)Impl的定义。如果在标题中包含Impl的定义,则将其公开给包含它的任何文件。

答案 2 :(得分:1)

基本问题是,为了将impl放在堆栈上,代码需要知道调用站点上的impl类的大小,这意味着必须公开impl的类定义。 impl的重点是隐藏类定义。