带有包含类的标头的Pimpl
Pimpl with header containing the class
我遇到了一个实现,它将pimpl类作为头,并将其包含在pimpl实现中。这有道理吗?类似这样的东西:
UI.h
class UI {
public:
UI();
virtual ~UI();
// bunch of methods
private:
UIImpl* m_impl;
}
UIImpl.h
class UIImpl
{
public:
UIImpl( ...) ;
......
}
UIImpl.cpp
#include "UIImpl.h"
UIImpl::UIImpl()
{
//Actual Implementation
...
}
我认为PIMPL
的原因是将实现完全隐藏在cpp
文件中。头球攻门会破坏目的吗?
它们是不同类型的头。UI.h
是"公共"的——它是库的外部接口的一部分,供客户端使用。
UIImpl.h
是"私有的",就像UIImpl.cpp
一样。只要它从未包含在公共标头中,它就可以对客户端保持不可见,就像.cpp
本身一样。
将impl
类定义拆分为头文件可能有几个原因。也许其他一些实现类被传递了UIImpl&
参数。也许只在头上运行doxygen更容易。也许这只是项目政策。
底线是,它仍然是Pimpl,只要你不发布私有头。
我认为
PIMPL
的原因是将实现完全隐藏在cpp文件中。头球攻门会破坏目的吗?
不一定。pIMPL可以用于快速值交换(可能在C++11/move语义之前的体系结构中)、桥接设计模式或任何其他原因。
桥梁设计模式示例:
class WinImpl { virtual ~WinImpl() = 0; /* other interfaces here */ };
// different header file(s)
#ifdef WIN32
class WindowsWinImpl: public WinImpl { /* ... */ };
#else
class LinuxWinImpl: public WinImpl { /* ... */ };
#endif
// different header file
class Window { private: WinImpl* pImpl /*= OSWindowFactory::CreateImpl();*/ };
在这种情况下,您有一个pImpl模型,在Window
类的头中包含WinImpl
的定义是完全可以的(因为目的不是隐藏实现,而是抽象它的接口)。
这样做非常合理。它允许修改UIImpl.h
(和相关的.cpp),而不必更改依赖于UI.h
的代码。由于UIimpl
类只是作为一个指针存储[并且假设UI本身只能访问UIimpl
类的公共方法,因此UI.h
代码对UIimpl类一无所知
事实上,您可能需要"UIimpl.h"来允许UI
类查看该类的公共功能。
例如
class UIImpl
{
public:
UIImpl( ...) ;
void func() { ... }
}
class UI
{
public:
UI();
virtual ~UI();
// bunch of methods
void func() { m_impl->func(); }
...
}
为此,UI
需要知道UIimpl
类提供的公共接口。
是的,这确实有意义。
一个使用示例:在为多个操作系统开发的代码中,UI.h从独立于操作系统的代码中可见,而不是UIImpl.h。操作系统相关代码(实现代码)将同时看到标题UI.h和UIImpl.h
- C++ - 是否可以让子类按值包含包含类?
- 从内部类中的方法从包含类调用方法
- 按类成员的顺序对包含类对象的C++向量进行排序
- C++ 提升 - 包含类层次结构对象的类的序列化
- 如何配置 Doxygen 以在"Class Index"中包含类的类型定义?
- 无法从多态嵌套类访问包含类的成员
- 在包含类对象的C++中迭代映射
- C 函数调用包装器包含类成员功能作为模板参数
- 具有挑战性的数据文件格式,需要将其读取为包含类对象的数组的VAR
- C 中的堆是否包含类和结构对象,或者仅包含指针
- 重载运算符<包含类对象
- Qt C++ 初始化类和调用方法,其中包含类中的变量
- 包含类文件后的错误消息(多个定义的符号)
- 设置返回指向包含类的指针的函数的格式
- 使用 pimpl 移动类无法编译
- 如何在包含类的向量中使用 std::less
- 类 "list" 包含包含类的结构
- C 键入包含类命名的类型
- 在客户端的函数声明头文件中使用类头文件时C++消除包含类头文件的方法
- 带有包含类的标头的Pimpl