1

我最近了解了 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;
};

HWND 由 DirectX 在表示参数 ( D3DPRESENT_PARAMETERS::hDeviceWindow)中使用

4

3 回答 3

1

我会让getHandle(或更好地getWindowData返回 aWindowData *而不是 a void *。然后让WindowData只是“System/Window.h”文件中的前向声明。

在“Direct3D9”中,使用 的完整定义WindowData,因此:

HWND hwnd = _window.getWindowData()->windowHandle;

如果在稍后阶段,您移植到 Linux,您可以在内部拥有完全不同的结构WindowData[基于#ifdef __WIN32/#else实现方面的某种类型的结构]。

于 2013-09-08T09:33:51.130 回答
1

从功能上定义你需要做什么,然后在接口方面实现它。不要暴露(公开)指针。此后,根据 HWND 和平台特定 API 实现接口。

例如:

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() )
{
}
于 2013-09-07T22:37:30.103 回答
-1

您可以复制数据并返回 unique_ptr。或者您可以将 HWND 作为 void* 而不是 HWND* 返回,因为它只是一个指针,尽管这确实利用了实现。但请记住,其他人仍然可以通过 HWND 以某种方式更改您的窗口,我想您对此无能为力。

于 2013-09-07T21:20:16.753 回答