多平台 class 设计 C++

Multiplatform class design C++

我想到了一种非标准的方式来处理 C++ 中的多平台接口,并且想知道这是否通常是一个坏主意以及为什么。

目前我只能想到一个缺点:做这样的事情非常(?)不常见,也许乍一看它的工作原理并不明显:

我有一个将在不同平台上使用的 class,例如 CMat4x4f32(4x4 矩阵 class 使用 32 位浮点数)。 我的平台独立界面如下所示:

class CMat4x4f32
{
public:
    //Some methods

    #include "Mat4x4f32.platform.inl"
};

Mat4x4f32.platform.inl 看起来像这样:

public:
    // Fills the matrix from a DirectX11 SSE matrix
    void FromXMMatrix(const XMMatrix& _Matrix);

它只是向矩阵添加了一个依赖于平台的接口 class。

.cpp 和 Mat4x4f32.platform.inl 位于 "win32" 或 "posix" 等子文件夹内,因此在 win32 中我实现了 FromXMMatrix 函数。我的构建系统根据我构建的平台将这些子文件夹添加到包含路径。

我什至可以更进一步,实现一个位于 win32 内部的 .platform.cpp,它只包含我添加到该平台界面的功能。

我个人认为这是个好主意,因为它使编写和使用界面变得非常简单和干净。 特别是在我的渲染器库中,它大量使用了我的基础库中的 Matrix class,我现在可以在 DirectX 部分使用依赖于平台的函数 (FromXMMatrix),就好像我不需要担心任何其他平台一样。

在基础库本身中,我仍然可以使用通用矩阵接口编写平台独立代码。

我还有其他 classes,它在其中很有用:例如 Error class,它收集错误并自动将它们转换为可读消息并提供一些调试选项。 对于 win32,我可以从错误的 DirectX 和 Win32 HResults 创建错误实例,在 Linux 上,我可以从返回的 errno 创建它们。在基础库中,我有一个 class 使用公共错误接口管理这些错误。

它极大地减少了所需的代码,并防止了丑陋的平台依赖于 util classes。

那么这个设计是好是坏,有哪些替代方案?

听起来你在谈论使用桥接模式: http://c2.com/cgi/wiki?BridgePattern

根据我的个人经验,我开发了很多平台无关的接口,具体实现使用了这种模式并且效果很好,我经常将它与 Pimpl 惯用语一起使用: http://c2.com/cgi/wiki?PimplIdiom

作为备选方案,我发现这个站点通常非常适合解释各种模式和范例的优缺点: http://c2.com/cgi/wiki

我建议您改用 "pimpl":

class CMat4x4f32
{
public:
    CMat4x4f32();

    void Foo();
    void Bar();

private:
    std::unique_ptr<CMat4x4f32Impl> m_impl;
};

然后在构建文件配置中引入特定于平台的 .cpp 文件,例如您可以在其中定义特定于平台的函数:

class CMat4x4f32::CMat4x4f32Impl
{
public:
    void Foo() { /* Actual impl */ }
    void Bar() { /* Actual impl */ }

    // Fills the matrix from a DirectX11 SSE matrix
    void FromXMMatrix(const XMMatrix& _Matrix);
};

CMat4x4f32::CMat4x4f32() : m_impl(new CMat4x4f32Impl()) {}
CMat4x4f32::Foo() { m_impl->Foo(); }
CMat4x4f32::Bar() { m_impl->Bar(); }