使用 Pimpl 的目的

pImpl 不只是解决编译速度问题,主要是解决隐藏实现细节,保持二进制兼容的问题。

Pimpl

正常我们去实现一个类,先编写头文件,再去编写实现文件,类中方法实现写在 cpp 文件中,但是类的属性都写在了 h 文件中。

  • 头文件暴露了私有成员。

  • 实现和接口耦合在了一起,私有成员的实现和方法的实现分开了。

  • 如果有另外一个库使用了这个库,而你的这个库实现变了,头文件就会变,而头文件一旦变动,就需要所有使用了这个库的程序都要重新编译!这个代价是巨大的。所以,我们应该尽可能地保证头文件不变动,或者说,尽可能隐藏实现,隐藏私有变量。

  1. // foo.h - header file
  2. #include <memory>
  3. class foo
  4. {
  5. public:
  6. foo();
  7. ~foo();
  8. foo(foo&&);
  9. foo& operator=(foo&&);
  10. private:
  11. class impl;
  12. std::unique_ptr<impl> pimpl;
  13. };
  14. // foo.cpp - implementation file
  15. class foo::impl
  16. {
  17. public:
  18. void do_internal_work()
  19. {
  20. internal_data = 5;
  21. }
  22. private:
  23. int internal_data = 0;
  24. };
  25. foo::foo(): pimpl{std::make_unique<impl>()} {
  26. pimpl->do_internal_work();
  27. }
  28. foo::~foo() = default;
  29. foo::foo(foo&&) = default;
  30. foo& foo::operator=(foo&&) = default;