【问题标题】:Is it better to use `#ifdef` or inheritance for cross-compiling?使用`#ifdef`或继承进行交叉编译更好吗?
【发布时间】:2010-01-02 00:22:50
【问题描述】:

遵循我的previous question about virtual and multiple inheritance(在跨平台场景中) - 在阅读了一些答案后,我想到我可以通过保留服务器和客户端类来简化我的模型,并用 # 替换特定于平台的类ifdefs(这是我原本打算做的)。

使用此代码会更简单吗?这意味着至少会有更少的文件!缺点是它创建了一个有点“丑陋”并且稍微难以阅读的Foobar 类,因为到处都是#ifdefs。请注意,我们的 Unix Foobar 源代码永远不会传递给编译器,因此这与#ifdef 具有相同的效果(因为我们还使用#ifdef 来决定要调用哪个平台特定的类)。

class Foobar {
public:
  int someData;

#if WINDOWS
  void someWinFunc1();
  void someWinFunc2();
#elif UNIX
  void someUnixFunc1();
  void someUnixFunc2();
#endif

  void crossPlatformFunc();
};

class FoobarClient : public Foobar;
class FoobarServer : public Foobar;

注意:为了更简单的示例,省略了一些内容(ctor 等)。

更新:

对于那些想进一步了解本期背景的人,我真的建议浏览一下适当的mailing list thread。事情开始在第 3 篇文章中变得有趣起来。还有一个related code commit,你可以在这里看到真实的代码。

【问题讨论】:

  • 我的偏好是使用继承并创建class FuncsWin32 : public Foobarclass FuncsUnix : public Foobar。这允许构建器包含适当的小部件,而无需关心程序的其余部分。

标签: c++ cross-platform multiple-inheritance conditional-compilation


【解决方案1】:

最好在方法中包含依赖于平台的操作性质,以便类声明跨平台保持相同。 (即,在实现中使用#ifdefs)

如果你不能这样做,那么你的类应该是两个完全独立的类,每个平台一个。

【讨论】:

  • 如果可能的话,这绝对是要走的路。但是,只要调用代码不关心平台,一切(大部分)都很好。
  • 在我们的例子中,旧代码(我们正在重构)与每个平台紧密耦合,所以很遗憾,我不确定这是否适合我们。
【解决方案2】:

我个人的偏好是将 ifdef 魔法推送到 make 文件中,以便源代码尽可能保持干净。然后每个平台都有一个实现文件。这当然意味着您可以为所有受支持的系统提供一个通用接口。

编辑:

为跨平台开发绕过这种低分母设计的一种常见方法是不透明句柄习语。与ioctl(2) 逃逸路线的想法相同 - 有一个方法返回不透明的前向声明结构,为每个平台定义不同的(最好在实现文件中),并且仅在通用抽象不成立时使用它。

【讨论】:

    【解决方案3】:

    如果您完全确定不会在编译的操作系统上使用来自其他操作系统的函数,那么使用 ifdef 有很多优势:

    1. 未使用的代码和变量不会被编译到可执行文件中(不过智能链接在这里有点帮助)
    2. 很容易看到哪些代码是活动的
    3. 您将能够轻松地包含平台相关文件。

    但是,基于操作系统的分类仍然有它的好处:

    1. 您将能够确保在为某个平台进行更改时代码可以在所有平台上编译
    2. 代码和设计会更简洁

    后者是通过在类主体本身中 ifdefing 特定于平台的代码来实现的,或者只是在编译中 ifdefing 不支持的 OS 实例。

    【讨论】:

      【解决方案4】:

      我的偏好是将特定于平台的问题推送到 leaf-most 模块,并尝试将它们包装到一个通用接口中。将具体的方法、类和函数放入单独的翻译单元。让链接器和构建过程确定要组合哪些特定的翻译单元。这使得代码更简洁,调试时间更容易。

      根据经验,我有一个项目使用了#ifdef VERSION2。我花了一周的时间进行调试,因为一个模块使用了#ifdef VERSION_2。如果所有版本 2 特定代码都在版本 2 模块中,则更容易捕捉到一个微妙之处。

      【讨论】:

        【解决方案5】:

        为特定于平台的代码使用#ifdefs 是惯用的;特别是因为如果在另一个平台上启用了一个平台的代码,它甚至不会编译。听起来对我来说是个好方法。

        【讨论】:

          猜你喜欢
          • 2013-05-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-04-24
          • 2015-04-21
          • 2016-05-11
          相关资源
          最近更新 更多