如何从特定于平台的头文件中抽象代码

问题描述 投票:0回答:3

嗨,我正在尝试找到一种方法来防止包含特定于平台的头文件,例如

windows.h
。 奇怪的是,我找到的解决方案都不令我满意。也许无法实现。

我认为要实现这一目标需要使用多种技术。互联网上有很多例子,但我找不到任何有关某一方面的例子。有些东西必须与你的抽象对话/创造。这是一个例子:

这是渲染窗口渲染目标的真正简化版本。

//D3D11RenderWindow.h
#include <d3d11.h>
class D3D11RenderWindow: public GfxRenderWindow
{
public:
    bool initialize(HWND windowHandle);

private:
    HWND windowHandle_; /// Win32 window handle
};  

这并不是什么大问题,这是特定于平台的代码,仅由特定于平台的代码包含。但我们需要实际实例化这种类型,因此“入口点”也需要了解平台特定的代码。

例如工厂类:

//GfxRenderWindowFactory.h
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>

class GfxRenderWindow;

class GfxRenderWindowFactory
{
public:
    static std::unique_ptr<GfxRenderWindow> make(HWND windowHandle);
};

现在这个工厂类需要被库的“客户端”(这里是渲染器)包含进来。我不喜欢的是

#include <windows.h>
,因为它对我来说太容易出错,任何人
#includes
,即使他们不需要它,也会拥有所有的世界和窗口......预编译头不是一个解决方案,因为现在编译器强制要求所有 cpp 都具有
#include
(它是加快编译时间的宝贵工具,但不是将平台特定代码与可移植代码分开的工具)代码)

我的想法是将cpp中的

#include <windows.h>
放在其标头的
#include
之前,而不是像这样放在头文件中:

//GfxRenderWindowFactory.cpp
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
#include "GfxRenderWindowFactory.h"

/// Implementation of GfxRenderWindowFactory goed here ....

通过这种方式,它迫使任何想要使用此类的人

#include
相关平台特定的标头,并且他们将能够更好地判断是否将此标头包含在错误的位置(例如在自己的头文件之一中) .

您对此有何解决方案? 您认为我的解决方案怎么样?疯了吗?

我想指出,对我来说,正确编写可移植代码非常重要!像“只是

#include <windows.h>
,不用担心”这样的答案不是有效的答案。这对我来说不是一个好的编码习惯。

我希望我的问题说清楚了。如果不告诉我我会澄清

非常感谢!

编辑

通过与 hmjd 的一次简短对话,我想在头文件中保留 windows.h,因为我同意,这使得它更有用。因此,如果有一种方法可以防止包含在头文件中,并强制该文件只能包含在 cpp 中,那就太好了。这可能吗?

c++ cross-platform
3个回答
2
投票

使用预定义的宏,如

WIN32
,或由构建系统定义的宏还不够:

#ifdef WIN32
#include <windows.h>
#else
include other platform specific headers
#endif

这是一种常见的方法(FWIW 是我用过的唯一方法)。


1
投票

由于根本问题是将

HWND
传递给
GfxRenderWindowFactory::make
,因此不要让
GfxRenderWindowFactory::make
接受
HWND


0
投票

嘿,我从事 wxsmith 跨平台 GUI API 的工作。您需要做的第一件事是使用自己的句柄创建类。手柄是三件事之一:

  1. 空虚*。
  2. 班级 *.
  3. 结构*。

使用像这样的函数:

#define create_handle(handle) struct __##handle{unsigned int unused;}; typedef __##handle *##handle;

然后调用这个函数,它会创建一个结构体和一个指向结构体的指针。指针就是句柄。然后投射到你想要的任何reinterpret_cast(这里是你的句柄);完成后,您可以在目标文件或库或 dll 中像这样进行转换。并为您的窗口句柄进行全局定义,研究其他操作系统如何做到这一点,您就完成了。

© www.soinside.com 2019 - 2024. All rights reserved.