我遇到了一个将pimpl类作为标题的实现,并将其包含在pimpl实现中。它甚至有意义吗?像这样:
class UI {
public:
UI();
virtual ~UI();
// bunch of methods
private:
UIImpl* m_impl;
}
class UIImpl
{
public:
UIImpl( ...) ;
......
}
#include "UIImpl.h"
UIImpl::UIImpl()
{
//Actual Implementation
...
}
我在想PIMPL
的原因是将实现完全隐藏在cpp
文件中。有一个标题会失败吗?
答案 0 :(得分:2)
他们是不同类型的标题。 UI.h
是“公共的” - 它是库的外部接口的一部分,供其客户使用。
UIImpl.h
是“私有的”,就像UIImpl.cpp
一样。只要它永远不会包含在公共标题中,它就会对客户端保持不可见,就像.cpp
本身一样。
将impl
类定义拆分为头文件可能有多种原因。也许其他一些实现类传递了UIImpl&
个参数。也许只在标题上运行doxygen更容易。也许这只是项目政策。
最重要的是,它仍然是Pimpl,只要你不发布私有标题。
答案 1 :(得分:1)
这样做很有意义。它允许修改UIImpl.h
(和相关的.cpp),而无需更改依赖于UI.h
的代码。由于UIimpl
类仅存储为指针[并且可能UI本身只能访问UIimpl
类的公共方法,因此UI.h
代码不知道UIimpl类。
事实上,你可能需要“UIimpl.h”来允许UI
类看到类的公共功能。
E.g。
class UIImpl
{
public:
UIImpl( ...) ;
void func() { ... }
}
class UI
{
public:
UI();
virtual ~UI();
// bunch of methods
void func() { m_impl->func(); }
...
}
要使其正常工作,UI
需要知道UIimpl
类提供的公共接口。
答案 2 :(得分:1)
我在想
PIMPL
的原因是将实现完全隐藏在cpp文件中。有一个标题会失败吗?
不一定。 pIMPL可用于快速值交换(可能在C ++ 11 /移动语义之前的体系结构中),桥接设计模式或任何其他数量的其他原因。
桥梁设计模式的一个例子:
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模型,在WinImpl
类的标题中包含Window
的定义是完全可以的(因为目的不是为了隐藏实现而是为了抽象这是界面)。
答案 3 :(得分:0)
是的,确实有意义。
使用示例:在为多个操作系统开发的代码中,UI.h可以从与操作系统无关的代码中看到,但不是UIImpl.h。依赖于操作系统的代码(实现代码)将同时看到头文件,UI.h和UIImpl.h