📜  C++中的PImpl成语示例(1)

📅  最后修改于: 2023-12-03 15:14:02.746000             🧑  作者: Mango

C++中的PImpl Idiom

在C++中,PImpl是一种设计模式,也被称为Opaque Pointer Idiom。它的全称是Private Implementation(私有实现)。PImpl的主要目标是将类的实现细节隐藏在类外部的唯一指针中,从而在不影响类的接口的情况下,允许对类的实现进行更改。

为什么需要PImpl Idiom?

C++在编译时需要把类的所有实现细节放在头文件中,这使得实现细节也变为了公共API,同时也带来了一系列问题。如果任何一个实现细节发生了变化,那么头文件就必须重新编译,并重新分发给所有用户。这会导致代码的重新编译和链接,这些都是工作量巨大的。PImpl Idiom的出现解决了这个问题。

使用PImpl Idiom,可以将实现细节封装起来,使得头文件仅包含接口和唯一指向实现的指针,这种设计模式可以最大程度地减少重新编译和重新分发的工作量。

如何实现PImpl Idiom?

下面是一个模拟PImpl实现的类示例:

// sample_class.hpp

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

    // Some public interface
    void PublicApi();
private:
    class Impl;
    std::unique_ptr<Impl> m_impl;
};
// sample_class.cpp

class SampleClass::Impl
{
public:
    void PrivateApi()
    {
        // Some implementation details
    }
};

SampleClass::SampleClass()
    : m_impl(std::make_unique<Impl>())
{
}

SampleClass::~SampleClass() = default;

void SampleClass::PublicApi()
{
    m_impl->PrivateApi();
}

在上面代码中,SampleClass被设计成只包含一个唯一指向私有实现的指针,所有的实现细节都在sample_class.cpp文件中。这意味着如果sample_class.cpp文件中的实现细节发生了变化,那么只有它需要重新编译和链接,而头文件不需要重新编译。

PImpl Idiom的优缺点
优点
  • 实现细节被封装在唯一指针中,可以随意变更细节而不会影响到头文件。
  • 前向引用可以用于减少编译时间和对象代码大小。
  • 可以隐藏某些不需要全部开放的成员函数,从而保持类接口的简洁。
缺点
  • 会带来一些性能损失,因为需要使用间接调用。
  • 不适用于需要更高内联性的函数,在这种情况下,我们不希望把函数成员的实现放在单独的编译单元中。
总结

PImpl Idiom是在C++中隐藏实现细节、减少重新编译和重新分发的工作量的一种优秀的设计模式。虽然PImpl Idiom会影响代码的性能,但是在大部分情况下,我们可以选择使用这个设计模式以减轻开发和维护工作量。