9

我需要维护一个支持在 Linux 和 Windows 上运行的项目。一些使用像这样的预处理器指令的代码很好。

#ifdef _WIN32 // _WIN32 is defined by Windows 32 compilers
#include <windows.h>
#else
#include <unistd.h>
#endif

但有些是实际的实现,我想阻止使用预处理器指令。

void Foo()
{

    #ifdef _WIN32 // _WIN32 is defined by Windows 32 compilers
    code for windows 
    #else
    code for Linux
    #endif

    some common code...

    #ifdef _WIN32 // _WIN32 is defined by Windows 32 compilers
    code for windows again
    #else
    code for Linux again
    #endif

}

因此,事情变得复杂且难以维护。有没有更好的办法?

4

5 回答 5

9

传统的方法是在包装函数中“隐藏”特定于任何操作系统的所有代码 - 您可以在具有更高级别功能的完整函数中执行此操作 - 例如,具有基于给定路径返回所有目录条目的函数作为输入,或实现各个基本功能,例如, start_read_directory(path)-这只是一个示例功能,相同的原理可以应用于几乎任何系统特定功能。将其包装得足够多,您将无法说出您正在编程的目的。read_dir_entry()end_read_directory()

从本质上讲,如果您在代码本身中有很多#ifdef,那么您就做错了。

于 2013-01-29T21:11:02.300 回答
8

处理来自构建系统的操作系统细节,而不是代码。例如,有两个版本的 Foo.cpp:一个在 Linux 上编译,另一个在 Windows 上编译。理想情况下,头文件将是通用的,并且所有函数签名都相同。

于 2013-01-29T21:15:44.817 回答
6

您可以使用工厂模式的简化版本。

有一个通用的接口

class MyClass
{
public:
    virtual void Foo() = 0;
};

并且为每个平台创建一个特定的类

#import <windows.h>
class MyClassWindows : MyClass
{
public:
    virtual void Foo() { /* Do something */ }
};

#import <linux.h>
class MyClassLinux : MyClass
{
public:
    virtual void Foo() { /* Do something */ }
};

然后当你需要这个类时,你使用你的工厂:

class MyClassFactory
{
public:
    static MyClass* create()
    {
        #if defined _WIN32
            return new MyClassWindows();
        #elif defined _LINUX
            return new MyClassLinux();
        #endif
    }
}

此方法有许多变体,包括在每个特定于平台的类的 .cpp 中定义 MyClassFactory::create 方法,并且只为适当的平台编译 .cpp。这避免了所有预处理指令,通过选择正确的实现文件进行切换。

于 2013-01-29T21:11:12.887 回答
4

一种常见的模式是提供与系统无关的头文件和特定于平台的实现文件。

标头中没有特定于平台的内容:

class Foo
{
   ...
};

在两个不同的实现文件中, foo_linux.cpp

 Foo::Foo() { .. linux code }

foo_windows.cpp

Foo::Foo() { .. windows code }

并且可能在 foo.cpp 中实现平台独立

void Foo::plat_independent_function()

您的平台构建然后链接 foo.cpp 和 foo_platform.cpp

于 2013-01-29T21:18:58.657 回答
0

实现这一点的一种可能性是使用 PIMPL 习惯用法,您的类只是发布“接口”并声明一个指向实现类的无意义指针(在其黑暗、隐藏和私有的角落),构建系统负责拉在包含 PIMPL 实现的类的正确平台相关代码中。

于 2013-01-29T21:24:04.110 回答