C++ 从不透明指针传输私人数据

C++ Communicating private data from opaque pointer

本文关键字:数据 传输 指针 不透明 C++      更新时间:2023-10-16

我最近了解到C++中的不透明指针。 我已经开始使用它们来隐藏特定于平台的私人成员。 例如在<windows.h>等中引用定义。

现在,我有几个相互构建的系统,需要相互通信。 例如,需要窗口句柄 (HWND) 的 Direct3D。 我不想向我的核心系统公开平台定义,但是我的子系统需要传达这些数据。

我正在公开不透明的数据并允许通过空指针进行访问。 这允许访问所有私有数据。

示例用法(主要.cpp):

// System:: namespace is my platform specific code
System::Window window;
System::DirectX::Direct3D9 gfxcontext(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!

有没有办法在子系统之间传达平台特定信息,而不会将其暴露给我的独立代码 - 并保持私有数据的私密性?


编辑当前窗口数据实现

struct Window::WindowData
{
    static LRESULT CALLBACK MessageHandler(HWND, UINT, WPARAM, LPARAM);
    HWND windowHandle;
    WNDCLASSEX windowClass;
    HINSTANCE processInstance;
};

HWND 被 DirectX 用于演示参数 ( D3DPRESENT_PARAMETERS::hDeviceWindow

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

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

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

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

在功能上定义你需要做什么,然后根据接口实现它。不要公开(公开)指针。此后,根据 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() )
{
}

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