简体   繁体   English

使用`#ifdef`或继承进行交叉编译会更好吗?

[英]Is it better to use `#ifdef` or inheritance for cross-compiling?

To follow from my previous question about virtual and multiple inheritance (in a cross platform scenario) - after reading some answers, it has occurred to me that I could simplify my model by keeping the server and client classes, and replacing the platform specific classes with #ifdefs (which is what I was going to do originally). 从我之前关于虚拟和多重继承的问题 (在跨平台场景中)开始 - 在阅读了一些答案后,我发现我可以通过保留服务器和客户端类来简化我的模型,并用以下内容替换特定于平台的类#ifdefs(这是我原本打算做的)。

Will using this code be simpler? 使用这段代码会更简单吗? It'd mean there'd be less files at least! 这意味着至少会有更少的文件! The downside is that it creates a somewhat "ugly" and slightly harder to read Foobar class since there's #ifdefs all over the place. 缺点是它会产生一些“丑陋”,并且稍微难以阅读Foobar类,因为#ifdefs遍布整个地方。 Note that our Unix Foobar source code will never be passed to the compiler, so this has the same effect as #ifdef (since we'd also use #ifdef to decide what platform specific class to call). 请注意,我们的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;

Note: Some stuff (ctor, etc) left out for a simpler example. 注意:有些东西(ctor等)遗漏了一个更简单的例子。

Update: 更新:

For those who want to read more into the background of this issue, I really suggest skimming over the appropriate mailing list thread . 对于那些想要更多地了解这个问题的人,我真的建议浏览相应的邮件列表线程 Thing start to get interesting around the 3rd post. 在第3篇文章开始变得有趣。 Also there is a related code commit with which you can see the real life code in question here. 还有一个相关的代码提交 ,您可以在此处查看有问题的真实代码。

Preferably, contain the platform dependant nature of the operations within the methods so the class declaration remains the same across platforms. 优选地,包含方法内操作的平台依赖性,因此类声明在不同平台上保持相同。 (ie, use #ifdefs in the implementations) (即在实现中使用#ifdefs)

If you can't do this, then your class ought to be two completely separate classes, one for each platform. 如果你不能这样做,那么你的课应该是两个完全独立的课程,每个平台一个。

My personal preference is to push ifdef magic into the make files, so the source code stays as clean as possible. 我个人的偏好是将ifdef magic推入make文件,因此源代码保持尽可能干净。 Then have an implementation file per platform. 然后每个平台都有一个实现文件。 This of course implies you can come up with an interface common for all your supported systems. 这当然意味着您可以为所有支持的系统提供通用接口。

Edit: 编辑:

One common way of getting around such a lower denominator design for cross-platform development is an opaque handle idiom. 绕过这种较低分母设计进行跨平台开发的一种常见方法是不透明的句柄习语。 Same idea as ioctl(2) escape route - have a method returning opaque forward-declared structure defined differently for each platform (preferably in the implementation file) and only use it when common abstraction doesn't hold. ioctl(2)转义路径相同的想法 - 有一个方法返回为每个平台(最好是在实现文件中)定义不同的不透明前向声明结构,并且只有当公共抽象不成立时才使用它。

If you're fully sure that you won't use functions from the other OS on the one compiled, then using ifdef's has a lot of advantages: 如果你完全确定你不会在编译的那个上使用其他操作系统的功能,那么使用ifdef有很多优点:

  1. Code and variables non used won't be compiled into the executable (however smart-linking helps here a bit) 未使用的代码和变量将不会被编译到可执行文件中(但是智能链接在这里有点帮助)
  2. It will be ease to see what code is live 可以轻松查看代码是什么
  3. You will be able to easily include platform dependent files. 您将能够轻松地包含平台相关文件。

However, classing based on OS can still have it's benefits: 但是,基于操作系统的分类仍然可以带来好处:

  1. You'll be able to be sure that the code compiles on all platforms when doing changes for one 在对一个平台进行更改时,您将能够确保代码在所有平台上编译
  2. The code and design will be cleaner 代码和设计将更清洁

The latter is achieved by ifdefing platform-specific code in the class bodies themselves, or just ifdefing out the non-supported OS instances in compilation. 后者是通过在类主体本身中定义特定于平台的代码来实现的,或者只是在编译时定义不支持的OS实例。

My preference is to push platform specific issues to the leaf-most modules and try to wrap them into a common interface. 我倾向于将平台特定问题推送到最多的模块,并尝试将它们包装到一个通用接口中。 Put the specific methods, classes and functions into separate translation units . 将特定方法,类和函数放入单独的翻译单元中 Let the linker and build process determine which specific translation units to combine. 让链接器和构建过程确定要组合的特定转换单元 This makes for much cleaner code and easier debugging times. 这样可以实现更清晰的代码和更简单的调试时间。

From experience, I had a project that used #ifdef VERSION2 . 根据经验,我有一个使用#ifdef VERSION2的项目。 I spent a week in debugging because one module used #ifdef VERSION_2 . 我花了一个星期的时间进行调试,因为一个模块使用了#ifdef VERSION_2 A subtlety that would be easier to catch if all the version 2 specific code was in version 2 modules. 如果所有版本2特定代码都在版本2模块中,则更容易捕获的微妙之处。

Having #ifdefs for platform specific code is idiomatic; 将#ifdefs用于平台特定代码是惯用的; especially since code for one platform won't even compile if it's enabled on another. 特别是因为如果一个平台的代码在另一个平台上启用,它甚至都不会编译。 Sounds like a good approach to me. 听起来对我很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM