Pimpl(Pointer to implementation)是一种C++编程技术,用于将类的实现细节与其接口分离。通常情况下,类的实现细节会暴露在类的头文件中,这会增加代码的复杂性并使得类的修改和维护变得困难。使用Pimpl技术,可以在类的头文件中只暴露必要的接口,而将具体实现细节放在单独的实现文件中,通过指向这个实现的指针来访问。
Pimpl技术可以带来以下好处:
- 将类的实现细节隐藏起来,使得类的接口更加简洁和清晰。
- 降低了代码的耦合性,修改类的实现不会影响用户代码。
- 可以减小编译依赖关系,减少编译时间。
- 通过使用智能指针(如std::unique_ptr)可以避免内存泄漏和删除对象时的不一致性问题。
使用Pimpl技术也有一些缺点,如额外的内存开销和性能损耗等。因此,在实际应用中需要根据情况来权衡是否使用这种技术。
在实际项目中,当某个类作为接口需要导出时,可以考虑使用Pimpl,这样可以只暴露必要的接口,隐藏实现细节,降低耦合。
以下是Pimpl的例子:
// ---------------------- // interface (widget.hpp) #include <experimental/propagate_const> #include <iostream> #include <memory> class widget { class impl; std::experimental::propagate_const<std::unique_ptr<impl>> pImpl; public: void draw() const; // public API that will be forwarded to the implementation void draw(); bool shown() const { return true; } // public API that implementation has to call widget(); // even the default ctor needs to be defined in the implementation file // Note: calling draw() on default constructed object is UB explicit widget(int); ~widget(); // defined in the implementation file, where impl is a complete type widget(widget&&); // defined in the implementation file // Note: calling draw() on moved-from object is UB widget(const widget&) = delete; widget& operator=(widget&&); // defined in the implementation file widget& operator=(const widget&) = delete; }; // --------------------------- // implementation (widget.cpp) // #include "widget.hpp" class widget::impl { int n; // private data public: void draw(const widget& w) const { if (w.shown()) // this call to public member function requires the back-reference std::cout << "drawing a const widget " << n << '\n'; } void draw(const widget& w) { if (w.shown()) std::cout << "drawing a non-const widget " << n << '\n'; } impl(int n) : n(n) {} }; void widget::draw() const { pImpl->draw(*this); } void widget::draw() { pImpl->draw(*this); } widget::widget() = default; widget::widget(int n) : pImpl{std::make_unique<impl>(n)} {} widget::widget(widget&&) = default; widget::~widget() = default; widget& widget::operator=(widget&&) = default; // --------------- // user (main.cpp) // #include "widget.hpp" int main() { widget w(7); const widget w2(8); w.draw(); w2.draw(); }
参考:
【1】https://blog.csdn.net/qq_21438461/article/details/132900415
【2】https://en.cppreference.com/w/cpp/language/pimpl
标签:default,widget,const,Implementation,draw,PImpl,implementation,Pimpl,Pointer From: https://www.cnblogs.com/kuaixue/p/18159184