使用#ifdef或继承进行交叉编译哪个更好?
从我的 上一个问题开始关于虚拟和多重继承(在跨平台场景中)-在阅读了一些答案后,我想到可以通过保留服务器和客户端类并用 #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 等)。
更新:
对于那些想要详细了解此问题背景的人,我强烈建议浏览相应的 邮件列表线程。从第三篇文章开始,事情开始变得有趣。另外还有一个相关代码提交,您可以使用它可以在这里看到有问题的现实生活代码。
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).
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. 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).
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.
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. Also there is a related code commit with which you can see the real life code in question here.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
最好在方法中包含操作的平台相关性质,以便类声明在跨平台上保持相同。 (即,在实现中使用#ifdefs)
如果您不能做到这一点,那么您的类应该是两个完全独立的类,一个用于每个平台。
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)
If you can't do this, then your class ought to be two completely separate classes, one for each platform.
我个人的偏好是将
ifdef
魔法推送到 make 文件中,以便源代码尽可能保持干净。然后为每个平台提供一个实现文件。这当然意味着您可以为所有支持的系统提供一个通用的接口。编辑:
解决跨平台开发的这种下分母设计的一种常见方法是不透明句柄习惯用法。与 ioctl(2) 转义路径相同的想法 - 有一个方法返回为每个平台定义不同的不透明前向声明结构(最好在实现文件中),并且仅在公共抽象不成立时才使用它。
My personal preference is to push
ifdef
magic into the make files, so the source code stays as clean as possible. 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.如果您完全确定不会在编译的操作系统上使用其他操作系统的函数,那么使用 ifdef 有很多优点:
然而,基于操作系统的分类仍然有它的好处:
后者是通过 ifdefing 中的特定于平台的代码来实现的类体本身,或者只是在编译时定义出不支持的操作系统实例。
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:
However, classing based on OS can still have it's benefits:
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.
我的偏好是将平台特定问题推送到最叶模块,并尝试将它们包装到一个通用接口中。将特定的方法、类和函数放入单独的翻译单元中。让链接器和构建过程确定要组合哪些特定的翻译单元。这使得代码更加简洁并且调试时间更加容易。
根据经验,我有一个使用
#ifdef VERSION2
的项目。我花了一周时间进行调试,因为一个模块使用了#ifdef VERSION_2
。如果所有版本 2 特定代码都在版本 2 模块中,则更容易捕捉到这一微妙之处。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
. I spent a week in debugging because one module used#ifdef VERSION_2
. A subtlety that would be easier to catch if all the version 2 specific code was in version 2 modules.使用 #ifdefs 来表示特定于平台的代码是惯用的;特别是因为如果在另一个平台上启用了某个平台的代码,则该代码甚至无法编译。对我来说听起来是个好方法。
Having #ifdefs for platform specific code is idiomatic; especially since code for one platform won't even compile if it's enabled on another. Sounds like a good approach to me.