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

时间:2012-12-06 12:43:48

标签: c++ design-patterns

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

选项1:PImpl-idiom

class RwMutex
{
    // .....
private:
   struct Impl;
   Impl*   m_Impl;
}
  • Pro:Cpp。
  • 中隐藏的实施和平台类型
  • 骗局:涉及两阶段建设('新',我们没有例外)可能会失败。辛苦做。

选项2:命名空间函数

class RwMutex {
public:
    bool LockRead() {return RwMutexLockRead( this );}
private:
    char m_AnonymousMember[ 16 ];
}
bool RwMutexLockRead( RwMutex* p );
  • Pro:实现可以直接链接到它,非常适合将它自己放入库中。
  • Con:涉及保留该成员的空间的reinterpret_cast。在调试器中不好用。还有很多工作要做。

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

2 个答案:

答案 0 :(得分:4)

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

选项2,在您实施时,不应使用。见GotW #28: The Fast Pimpl Idiom。但是,在C ++ 11中,可以使用std::aligned_storage<>正确完成此操作。我曾经写过一个pimpl_ptr<T, Size, Align=default>来为你做铸造,复制,析构函数调用,并检查你选择了正确的Size

一般情况下,使用pimpl除非您已经分析并证明这是瓶颈。

但与往常一样,不要重新发明轮子。 Mutex和Threads是新C ++ 11标准的一部分,因此要么升级编译器,要么使用Boost。对于文件使用Boost。原因是,新C ++ 11库的许多部分都来自Boost。

答案 1 :(得分:2)

为什么甚至有一个Implementation对象?您的代码不仅会在同一平台上进行更改,而且您将在当前使用的平台上使用相同的实现。在标头中定义接口,并为您要定位的每个平台提供各种* .cpp文件。使用#ifndef,#else等。

e.g。 您的文件系统可能如下所示:

include/
    RwMutex.hpp
    // etc...
src/
    RwMutex/
       RwMutexWin32.cpp
       RwMutexUnix.cpp
       // etc... 

这是RwMutexWin32.cpp的样子:

#ifdef MYLIBPREFIX_PLATFORM_WIN32
#include "RwMutex.hpp"

#include <Windows.h>

// implement the Windows version of the RwMutex class

另一个例子可能是查看SDL,或用C或C ++编写的其他一些跨平台库。它们主要使用预处理器系统。你不太可能想要改变Impl对象指向的东西(即Windows机器上的Unix实现没有意义,也不会编译)。

当然,如果你真的想这样做,我建议你使用CMake。但正如其他人建议的那样,您应该尝试使用其他库,例如booststandard library,它已经为您编写。