Pimpl是“实现指针”的缩写,它提供了一种方便的方法来隐藏类中的实现。我正在实现一个 Window 类,它对此类的用户隐藏特定于平台的功能和结构,因此类接口最终看起来很干净:
class Window{
public:
/// Constructors & destructors:
Window(void);
Window(Window const& window_);
Window(Window&& window_);
explicit Window(std::string const& title_);
explicit Window(std::string&& title_);
~Window(void);
/// Member data:
bool visible = false;
ContextGraphics graphics_context;
std::array<unsigned long, 2> position = {{0}}, size = {{800, 600}};
std::string title;
/// Member functions:
void apply_changes(void);
Window& center_position(void);
bool enabled(void) const;
void update(void);
/// Member functions (overloaded operators, assignment):
Window& operator=(Window const& window_);
Window& operator=(Window&& window_);
private:
/// Inner classes:
class Helper;
/// Member data:
std::unique_ptr<Window::Helper> _m_opHelper;
};
幕后都是那些讨厌的 WINAPI 调用等,当我可能针对更广泛的支持平台时,类头根本不需要更改,只需要更改源文件。非常好用,不用写那么多!
但是,这个对象似乎是我的问题(在类内):
ContextGraphics graphics_context;
这是一个 Direct3D/OpenGL 图形上下文(“ContextGraphics”的用户可以确定),您可能已经猜到,它也使用 pimpl-idiom:
class ContextGraphics{
/// Friends:
friend class Window;
public:
/// Enumerations:
enum class API : unsigned int{
API_DEFAULT,
API_DIRECT3D,
API_OPENGL
};
/// Constructors & destructors:
ContextGraphics(void);
explicit ContextGraphics(ContextGraphics::API const& api_);
explicit ContextGraphics(ContextGraphics::API&& api_);
~ContextGraphics(void);
/// Member data:
ContextGraphics::API api = ContextGraphics::API::API_DEFAULT;
unsigned int color_depth : 6; // 2 ^ 6 = 64
/// Member functions:
bool api_available(void) const noexcept;
bool enabled(void) const;
/// Member functions (overloaded operators, assignment):
ContextGraphics& operator=(ContextGraphics const& context_graphics_);
ContextGraphics& operator=(ContextGraphics&& context_graphics_);
private:
/// Constructors & destructors:
ContextGraphics(ContextGraphics const& context_graphics_);
ContextGraphics(ContextGraphics&& context_graphics_);
/// Inner classes:
class Helper;
/// Member data:
std::unique_ptr<ContextGraphics::Helper> _m_opHelper;
/// Member functions:
void create(void);
void destroy(void);
};
我面临的问题是编译器:
Window.cpp|145|错误:无效使用不完整类型'class ContextGraphics::Helper'|
ContextGraphics.hpp|43|错误:'class ContextGraphics::Helper'的前向声明|
编译器似乎没有找到类“ContextGraphics::Helper”的实现,这只会引发一个问题,即带有 pimpl 的类是否可以使用带有 pimpl 的对象。如果不将所有实现都放在 Window 类源文件中,这可能吗?对我来说,这似乎不是一个合理的解决方案。