The C++ Pimpl(Pimpl模式)

本文介绍了C++Pimpl模式的目的,即为了类的实现和类本身解耦,同时达到类的内部实现对于类的使用者透明。通过使用Pimpl模式,可以减少类的公共接口变更时的编译损害。文章详细解释了如何在类定义文件中定义私有实现类,并通过成员指针与客户端交互。同时提供了进阶技巧,如私有方法调用公共方法、使用智能容器代替原始指针等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

pimpl模式的目的:是为了类的实现和类本身解耦,同时达到类的内部实现对于类的使用者透明。


Introduction


Despite the similarity, the C++ Pimpl has nothing to do with sex. The C++ Pimpl is a short form for "Private Implementation" idiom, and its usage is popularized in Herb Sutter's Guru of the Week ( www.gotw.ca ) column. (Note: The L behind is used to protect the underage)

The Pimpl idiom describes a way for making your header files impervious to change. You often hear advices like "Avoid change your public interface!" So you can modify your private interface, but how can you avoid recompilation when  your header file defines the private methods . This is what the Pimpl does – Reduce compilation damages when your private interface changes.

Just like real life, we often judge a Pimpl by what it has to offer, so let's see what it does.


Pimpl in Action

Let's get straight to business. Here is the Pimpl.

Note: I avoid unnecessary things like header inclusion guards for simplicity.

// 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
};

Our header defines a forward declaration of the Pimpl and other public interface. It stores a private Pimpl_ member pointer and that is all the client will ever see. There will never be any change unless you change the public interface, which you already know you shouldn't.

The definition file goes as follows

// 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;
}

We define the private implementation class in the class definition file. We access private methods through the member pimpl_ pointer.

We can add, remove, and change the implementation class anyway we like. The client is totally insulated through the forward declaration and pointer declaration of Pimpl;


Being a PRO

If you want to be more of a PRO (professional, that is), here are tips.

1. Private methods calling public methods
Often your private methods need to call public methods. If that is the case, the private implementation class can store a reference to the main class and use the reference to access the main class. Watch out for methods calling each other though, it will lead to infinite recursion.

2. Using a smart container instead of a raw Pimpl pointer.
In the example, I disallowed copying and assignment in the class. Should you want to allow it, you can use a smart pointer class (The STL auto_ptr doesn't cut it) to hold the Pimpl instead. This saves you from having the common shallow/deep copies pointer problems.

3. Defining the private implementation class as a local class instead.
The Pimpl idiom pollutes the namespace with another class. If you want to avoid that, you can implement the private implementation class as a local class instead. However, do note that local classes have many restrictions.


If you need it, get it

At the end of the day, the question you always need to ask is, "Was it worth it?"

The class has to store an additional pointer member. Calling methods require an additional pointer deference call. For small classes (like matrices classes) which are used often, the speed and memory increase may be unacceptable. For other types of classes, the impact is negligible.

Use it appropriately and it should satisfy just right. Remember,

Always practice safe coding. Use an assert.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值