我最近在C ++中学到了不透明指针。我已经开始使用它们来隐藏特定于平台的私有成员。例如<windows.h>
等中对定义的引用
现在,我有几个系统相互建立并需要相互通信。例如,Direct3D需要一个窗口句柄(HWND)。我不想将平台定义暴露给我的核心系统,但我的子系统需要传达这些数据。
我正在暴露不透明数据并允许通过void指针进行访问。这允许访问所有私人数据。
示例用法(main.cpp):
// System:: namespace is my platform specific code
System::Window window;
System::DirectX::Direct3D9 gfxcontext(window);
窗口定义(System / Window.h):
class Window
{
WindowData* data; // Opaque pointer
public:
void* getHandle() const; // returns an HWND handle
Window();
~Window();
}
如何检索有用数据(Direct3D9.cpp):
#include "Window.h"
Direct3D9::Direct3D9(const Window& _window)
{
HWND windowHandle = *(HWND*)_window.getHandle();
// [...]
pp.hDeviceWindow = windowHandle;
}
但是,此代码有效!:
*(HWND*)_window.getHandle() = 0; // changes HWND in WindowData to NULL!
有没有办法在子系统之间传递平台特定信息而不将其暴露给我的独立代码 - 并且保密私有数据?
编辑当前的WindowData实现
struct Window::WindowData
{
static LRESULT CALLBACK MessageHandler(HWND, UINT, WPARAM, LPARAM);
HWND windowHandle;
WNDCLASSEX windowClass;
HINSTANCE processInstance;
};
DirectND在演示参数(D3DPRESENT_PARAMETERS::hDeviceWindow
)
答案 0 :(得分:1)
在功能上定义您需要做什么,然后根据接口实现它。不要暴露(公开)指针。此后,根据HWND和特定于平台的API实现接口。
e.g:
struct WindowHandleImpl
{
virtual void show() = 0;
virtual void maximize() = 0;
//etc...
};
struct Win32WinHandleImpl : WindowHandleImpl
{
std::unique_ptr<HWND> handle_; //Use deleter...
virtual void show(); //In terms of HWND, using Win32 API
virtual void maximize();
};
struct XWinHandleImpl : WindowHandleImpl
{
//In terms of platform specific handle.
};
struct Window
{
void show(); //In terms of WindowHandleImpl
void maximize();//In terms of WindowHandleImpl
private:
std::unique_ptr<WindowHandleImpl> pimpl_;
};
Window::Window( const Factory& factory )
: pimpl_( factory.createWindow() )
{
}
//or
Window::Window()
: pimpl_( SystemFactory::instance().createWindow() )
{
}
答案 1 :(得分:1)
我会让getHandle
(或更好getWindowData
返回WindowData *
而不是void *
。然后让WindowData
成为“{1}}中的前向声明System / Window.h“文件。
在“Direct3D9”内,使用WindowData
的完整定义,所以:
HWND hwnd = _window.getWindowData()->windowHandle;
如果在稍后阶段,您移植到Linux,您可以在WindowData
[基于实现方中的某些#ifdef __WIN32/#else
类型的结构]内部具有完全不同的结构。
答案 2 :(得分:-1)
您可以复制数据并返回unique_ptr。或者你可以将HWND作为void *而不是HWND *返回,因为它只是一个指针,尽管它确实利用了实现。请记住,其他人仍然可以通过HWND以某种方式改变你的窗口,我想你无能为力。