C ++跨平台开发,以避免预处理器指令

时间:2013-01-29 20:59:34

标签: c++ cross-platform

我需要维护一个支持在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

}

所以事情变得复杂,难以维持。还有更好的办法吗?

5 个答案:

答案 0 :(得分:8)

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

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

答案 1 :(得分:8)

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

答案 2 :(得分:5)

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

有一个通用界面

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。这避免了所有预处理指令,通过选择正确的实现文件进行切换。

答案 3 :(得分: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

答案 4 :(得分:0)

实现这一点的可能性是使用PIMPL习惯用法,你的类只发布“接口”并声明一个无意义的指向实现类的指针(在它的黑暗,隐藏和私有角落),构建系统需要注意为包含PIMPL实现的类提供正确的平台相关代码。