如何写出优雅的跨平台的C/C++代码

在开发中,如何将代码做到跨平台,如何保持C/C++代码能够在多个平台上编译,是一个值得研究的问题。

此外,不同平台对某些操作有自己独特的优化,例如FFT(快速傅里叶变化)在android和ios上都有自己的独特的优化方式,如何在特定平台做优化,同样值得研究

混乱的 #ifdef

如何编写跨平台的代码呢?哥们,你脑袋里蹦出的第一个想法应该是使用:#ifdef

因此,你写的跨平台代码类似这样:
头文件:

// a.h
void print_something();

源文件:

// a.cpp
#include "a.h"

#ifdef _WIN32_
void print_something() 
{
    printf("_WIN32_");
}
#ifdef _LINUX_
void print_something() 
{
    printf("_LINUX_");
}
#ifdef _IOS_
void print_something() 
{
    printf("_IOS_");
}
#ifdef _ANDROID_
void print_something() 
{
    printf("_ANDROID_");
}
#endif

也许有成百上千处的代码充斥着这样一堆的#ifdef,说实话,自打我第一次看见这种实现方式时就觉得它不够优雅,它很混乱。

只编译特定平台的代码

更加优雅的方式就是:只编译特定平台的代码

利用cmake这样的工具,在CMakeLists.txt中,你知道你关心哪个平台,所以你可以只编译特定平台的.c/.cpp文件,构建项目并忽略其他平台的代码。当你阅读代码的时候,就不用再看到一段的#ifdef了,因为他们被分成了不同的文件,这些文件永远都不会在同一个版本中冲突

因此,我可以构建一个头文件a.h和四个不同的.cpp文件:a_win.cpp, a_linux.cpp, a_ios.cpp和a_android.cpp

然后在CMakeLists.txt中可以这么写:

if(WIN32)
    FILE(GLOB PLATFORM_SOURCES *_win.cpp)
elseif(LINUX)
    FILE(GLOB PLATFORM_SOURCES *_linux.cpp)
elseif(IOS)
    FILE(GLOB PLATFORM_SOURCES *_ios.cpp)
elseif(ANDROID)
    FILE(GLOB PLATFORM_SOURCES *_android.cpp)
endif()

add_library(a_lib ${PLATFORM_SOURCES})

这么做阅读和调整代码都非常简单,因为与平台相关的代码都单独放在一个文件中,比起原来丑陋的代码清晰了很多

Q&A

Q:只有少量的跨平台代码也要用这种方式吗?
A:不,如果只有少量的#ifdef并且不破坏代码的整洁,完全是可以接受的。因为我们的目的就是保持跨平台代码的整洁。

参考

  • A Better Way to Write Platform-specific C++ Code

你可能感兴趣的:(c++)