如何设计一个好的平台抽象层?

Bor*_*rph 5 c++ design-patterns

我们在我们的大项目中有中心类和函数来从实际的平台类型中抽象出来,例如互斥锁、文件、线程等,而不是在代码中到处都有“fopen”。虽然这很好,但我想更进一步,头文件中不包含任何系统(如#include <windows.h>),这将是真正的平台抽象和更快的编译。不利的一面是,您不能仅将 typedef 定义为系统类型(例如 Windows HANDLE)。

选项 1:PImpl-惯用语

class RwMutex
{
    // .....
private:
   struct Impl;
   Impl*   m_Impl;
}
Run Code Online (Sandbox Code Playgroud)
  • 优点:在 Cpp 中很好地隐藏了实现和平台类型。
  • 缺点:涉及可能失败的 2 阶段构建(“新”,我们没有例外)。做起来费劲。

选项 2:命名空间函数

class RwMutex {
public:
    bool LockRead() {return RwMutexLockRead( this );}
private:
    char m_AnonymousMember[ 16 ];
}
bool RwMutexLockRead( RwMutex* p );
Run Code Online (Sandbox Code Playgroud)
  • 优点:实现可以直接链接到它,非常适合将它单独放入库中。
  • 缺点:涉及保存成员的空间的 reinterpret_cast。在调试器中不好。工作量也很大。

也许我很渴望它,但是如果大量的项目代码可以清除任何依赖于平台的包含(可能由-nostdinc选项强制执行),那就太酷了。

ipc*_*ipc 4

使用指针的选项 1 是一个坏主意。boost::scoped_ptr如果可以的话,使用 或std::unique_ptr

当您实施选项 2 时,不应使用它。请参阅GotW #28:快速 Pimpl 习语。然而,在 C++11 中,可以使用std::aligned_storage<>. 我曾经写过一个pimpl_ptr<T, Size, Align=default>,它会为你执行强制转换、复制、析构函数调用,并检查你是否选择了正确的Size

一般来说,除非您已经分析并表明这是瓶颈,否则请使用 pimpl。

但一如既往,不要重新发明轮子。互斥体和线程是新 C++11 标准的一部分,因此要么升级编译器,要么使用 Boost。对于文件,请使用 Boost。原因是,新 C++11 库的许多部分都取自 Boost。