我正在研究如何在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)不需要更改和重新生成。 (他们仍然需要重新链接)
答案 0 :(得分:5)
pimpl-idiom的技巧是,在你的头文件中只使用一个指针。这意味着您可以使用类的前向声明,而无需实际提供声明。
因此,您可能稍后更改您的声明(在cpp中),而不会使用标题影响标题或其他编译单元。
这在处理库时特别有用。
答案 1 :(得分:1)
由于指针,你需要做一个新的事情。指针存在,因此您可以转发声明(即不包括)Impl的定义。如果在标题中包含Impl的定义,则将其公开给包含它的任何文件。
答案 2 :(得分:1)
基本问题是,为了将impl放在堆栈上,代码需要知道调用站点上的impl类的大小,这意味着必须公开impl的类定义。 impl的重点是隐藏类定义。