编译时多态性解决方案

C++11 - Compile time Polymorphism solutions

本文关键字:解决方案 多态性 编译      更新时间:2023-10-16

假设我正在编写一个跨平台库,我必须以一种不同平台有不同行为的方式组织代码,这种行为(或定义)是在编译时根据我的库正在编译的平台选择的。

在c++中这样做的"通常"方法是在编写方法或类时用大量的#ifdef污染代码。

方法的问题是:

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

由于c++ 11中有很多新特性,我想知道是否有什么改变,如果有新的选项。

您应该使用构建系统来完成此操作。应该在头文件中提供与平台无关的函数声明和类定义。然后,根据目标平台,构建系统应该编译这些函数和类的适当实现。

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

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

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

这有几个优点:

  1. 您已经将构建关注点(您正在构建的平台)从代码关注点中分离出来。
  2. 每个平台相关的实现都有自己的文件。
  3. 你不会有一个混乱的预处理器指令和难以跟踪执行路径的文件。

这并不意味着使用定义有选择地编译代码的不同部分有什么问题。我更愿意看到只有少量的代码已经本地化到平台相关的部分。理想情况下,将与平台相关的代码包装在一个函数中,并让#ifdef替换出实现。

确切地说,你如何做这个选择性构建取决于你正在使用的构建系统。对于GNU构建系统,您可以使用automake实现条件编译。文档中给出了一些示例。一个简单的例子是:

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

使用此配置运行automake将生成适当的makefile。