使用#ifdef是正确的策略吗?

Is Using #ifdef a correct strategy

本文关键字:策略 #ifdef 使用      更新时间:2023-10-16

所以,我有一个要求,做一个特定的任务(说多线程)是完全依赖于操作系统(或像win32/linux api调用)。

现在我在某处读到,使用#ifdef我们实际上可以编写与os相关的代码

#ifdef __linux__
/*some linux codes*/
#endif

现在我的问题是....

这是正确的方式来写我的代码(1)。E使用ifdef),然后释放一个单一的。cpp文件为Windows和linux?或者我应该把我的代码分成两部分,发布两个不同的版本——一个用于linux,一个用于windows?

编辑:

似乎问题太宽泛了,这产生了很多意见。

根据性能、构建大小等(我可能忽略的任何其他因素)区分我提到的两种方法。

Class A {
.
.// Some variables and methods
.
};
class B: public A {
    void DoSomething() {
    // COntains linux codes and some windows code
    }
};

如果假设我不使用#ifdef,我将如何编写dosomething()方法,在正确的时间调用正确的代码

解决方案#1:使用现有的、经过调试的、文档化的库(例如boost)来隐藏平台差异。它在内部使用了很多#ifdef,但是你不必担心。

解决方案#2:编写自己的独立于平台的库(参见解决方案#1以获得更好的方法),并隐藏所有的#ifdef。

解决方案#3:在宏中完成(呃,但请参阅ACE(尽管ACE的大部分也在库中)

解决方案#4:每当出现平台差异时,在整个代码中使用#ifdefs。

解决方案#4适用于非常小的、一次性的代码程序。如果你在20世纪90年代编程,解决方案#3是合适的。
解决方案#2只适用于由于非技术原因不能使用真正的库的情况。

结论:使用解决方案#1

这是可能使用#ifdef,但它很快导致不可维护的代码。一个更好的解决方案是抽象功能放入一个类中,并提供两个不同的该类的实现(两个不同的源文件)。(即使在C语言时代,我们也会在一个头文件,并为它们提供不同的源文件实现。)

我通常给源文件相同的名称,但put它们在平台相关的目录中,例如:thread.hhPosix/thread.ccWindows/thread.cc中的源。或者,您可以将实现放在文件中不同的名称:posix_thread.ccwindows_thread.cc .

如果你需要在头文件中使用依赖项,可以使用目录方法同样适用。或者你可以这样写:

#include systemDependentHeader(thread.hh)

,其中systemDependentHeader是一个宏,它做一些标记粘贴(使用命令行上定义的令牌)和stringizing .

当然,在线程的情况下,c++ 11提供了一个标准溶液,这是你应该用的;如果你不能,boost::thread离标准并不远(我认为)。更多的一般来说,如果你能找到已经完成的工作,你应该这样做好好利用它。(但要验证库的质量第一。过去,我们不得不放弃使用ACE,因为它bug太多了

如果你需要为不同的平台开发代码,你必须考虑以下几点:

您可以使用#ifdef or #if defined(x),但您必须将其限制在头文件中,如果该文件名为"platform.h"则更好。在源代码中,可以使用platform .h文件中定义的宏。因此,您的业务逻辑在两个平台上是相同的。

让我给你一个例子:

PLATFORM.H
// A platform depended print function inside platform.h file
#if defined( _EMBEDDED_OS_ )
  #include <embedded_os.h>
  #define print_msg(message) put_uart_bytes(message)
#elif defined( _WINDOWS_ )
  #include <windows.h>
  #define print_msg(message) printf(message)
#else
  #error undefined_platform
#endif

SOURCE.CPP
void main()
{
   print_msg("Ciao Mondo!");
}

正如您所看到的,每个平台的源代码都是相同的,您的业务逻辑没有被几个#ifdef指令弄脏