2013-04-06 106 views
3

假设我正在编写一个跨平台的库,我必须以一种对不同平台有不同行为的方式组织代码,并且这种行为(或定义)是在编译时选择基于我的库正在编译的平台。C++ 11 - 编译时多态解决方案

在C++中执行此操作的“通常”方法是在编写方法或类时污染代码,其中包含许多#ifdef

与方法的问题在于:

  • 的源代码看起来非常难看
  • 如果要支持3个平台上,你的源代码是不是你真正需要的约3倍,这意味着你的编译器仍然需要解析和分析所有的代码来“看”#ifdef
  • 在不同的实现之间没有真正的区别,当代码库增长时,很难保持,当你只有3-4个平台时,它增长得非常快。

由于在C++ 11中有很多新功能,我想知道是否有更改,如果有新的选项。

+1

如果不同实现之间没有真正的区别,那么'#ifdef'会做什么?你能举一个具体的例子吗? – 2013-04-06 09:54:37

+0

@AndyProwl我的意思是对于编码器来说,它并不整齐 – user2244984 2013-04-06 09:55:29

+0

我知道它并不整齐,但知道这些具体的差异可能有助于确定模板是否可以帮助 – 2013-04-06 09:57:19

回答

6

你应该使用你的构建系统来做到这一点。您应该为头文件提供平台无关的函数声明和类定义。然后,根据目标平台,构建系统应编译这些函数和类的适当实现。

例如,让我们考虑创建用于显示图形或GUI元素的窗口。如果您不使用库来执行此操作,则必须自己编写跨平台代码。首先,你应该仔细考虑平台独立接口应该是什么。也许你有一个window类和一些辅助函数。然后,您可以提供该类的定义以及头文件中的助手函数的声明,并为每个平台提供单独的实现。然后你就会有这样的一组文件:

  • window.h
  • window_wayland.cpp
  • window_winapi.cpp
  • window_x11.cpp

现在,所有需要使用你的类文件和函数应该只是#include <window.h>。他们都获得相同的函数声明。但是,您在构建系统的配置中指定应在具有X11窗口系统的系统上编译window_x11.cpp,在具有Wayland的系统上编写window_wayland.cpp,在Windows上编写window_winapi。这意味着取决于您正在构建的平台,您将获得可在目标平台上运行的该头的实现。

这有一个很好的一些优势:

  1. 你分开构建的担忧从码关注(你正在构建其平台)。
  2. 每个平台相关的实现都有自己的文件。
  3. 您没有一个文件凌乱与预处理器指令,难以遵循执行路径。

这并不意味着使用定义有选择性地编译代码的不同部分有任何问题。我更希望只有少量已经本地化到平台相关部分的代码才能看到这一点。理想情况下,将与平台相关的代码包装在一个函数中,并且只需将该实现换掉即可。

您究竟如何做这个选择性建设取决于您使用的构建系统。对于GNU构建系统,您可以使用automake实现条件编译。 Some examples are given in the documentation。给出一个简单的例子是:

bin_PROGRAMS = hello 
if LINUX 
hello_SOURCES = hello-linux.c hello-common.c 
else 
hello_SOURCES = hello-generic.c hello-common.c 
endif 

具有这种构造运行automake将产生适当的生成文件。

+0

你可以参考一下你的意思吗? – user2244984 2013-04-06 09:56:15

+0

所以你把'#ifdef'放在头文件中,而不是在执行/ .cpp文件中? – user2244984 2013-04-06 10:04:10

+0

@ user2244984根本没有'#ifdef'。您告诉您的构建系统根据平台编译不同的实现。每个平台都将看到完全相同的头文件。 – 2013-04-06 10:05:51