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

时间:2012-02-23 22:24:04

标签: c++ cross-platform

您好我正在尝试找到一种方法来阻止包含特定于平台的头文件,例如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”,因为它太容易出错我,任何包含它的人,即使他们不需要它也会拥有所有的世界和窗口....预编译header不是解决方案,因为现在编译器强制所有cpp都包含它(它是加速编译时间的有用工具,但不是将平台特定代码与可移植代码分开的工具)

我认为将#include放在cpp之前,而不是在头文件中包含它,如下所示:

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

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

这种方式强制任何想要使用这个类的人都包含相关的平台特定标题,他们可以更好地判断他们是否将这个标题包含在一个糟糕的地方,就像在他们自己的一个头文件中一样。 / p>

你有什么解决方案? 你觉得我的解决方案怎么样?,疯了吗?

我想指出,对我而言,正确执行便携式代码是非常重要的!像只包括windows.h的答案,不要冒汗它不是一个有效的答案。对我来说这不是一个好的编码实践。

我希望我明白我的问题。如果不告诉我,我会澄清

非常感谢!

##编辑## 从与hmjd的小谈话中,我想在头文件中保留windows.h,因为我同意,这使得它更有用。因此,有一种方法可以防止包含在头文件中,这样就可以强制执行该文件只能包含在cpp中。这可能吗?

3 个答案:

答案 0 :(得分:1)

使用预定义的宏(例如WIN32)或构建系统定义的宏是不够的:

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

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

答案 1 :(得分:1)

由于基本问题是将HWND传递给GfxRenderWindowFactory::make,因此GfxRenderWindowFactory::make没有HWND

答案 2 :(得分:0)

嘿,我参与了wxsmith跨平台GUI API。您需要做的第一件事是使用自己的句柄创建类。句柄是3件事之一:

  1. 无效*。
  2. Class *。
  3. Struct *。
  4. 使用如下函数:

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

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