嗨,我正在尝试找到一种方法来防止包含特定于平台的头文件,例如
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 中,那就太好了。这可能吗?
使用预定义的宏,如
WIN32
,或由构建系统定义的宏还不够:
#ifdef WIN32
#include <windows.h>
#else
include other platform specific headers
#endif
这是一种常见的方法(FWIW 是我用过的唯一方法)。
由于根本问题是将
HWND
传递给 GfxRenderWindowFactory::make
,因此不要让 GfxRenderWindowFactory::make
接受 HWND
。
嘿,我从事 wxsmith 跨平台 GUI API 的工作。您需要做的第一件事是使用自己的句柄创建类。手柄是三件事之一:
使用像这样的函数:
#define create_handle(handle) struct __##handle{unsigned int unused;}; typedef __##handle *##handle;
然后调用这个函数,它会创建一个结构体和一个指向结构体的指针。指针就是句柄。然后投射到你想要的任何reinterpret_cast(这里是你的句柄);完成后,您可以在目标文件或库或 dll 中像这样进行转换。并为您的窗口句柄进行全局定义,研究其他操作系统如何做到这一点,您就完成了。