从我的previous question about virtual and multiple inheritance开始(在跨平台场景中) - 在阅读了一些答案后,我发现我可以通过保留服务器和客户端类以及替换特定于平台的类来简化我的模型用#ifdefs(这是我原本打算做的)。
使用此代码会更简单吗?这意味着至少会有更少的文件!缺点是它创建了一个有点“难看”并且稍微难以阅读Foobar
类,因为整个地方都有#ifdefs
。请注意,我们的Unix Foobar源代码永远不会传递给编译器,因此它与#ifdef
具有相同的效果(因为我们还使用#ifdef
来决定要调用的平台特定类)。 / p>
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,你可以在这里看到现实生活中的代码。
答案 0 :(得分:10)
优选地,包含方法内操作的平台依赖性,因此类声明在不同平台上保持相同。 (即,在实现中使用#ifdefs)
如果你不能这样做,那么你的课应该是两个完全独立的课程,每个平台一个。
答案 1 :(得分:5)
我个人的偏好是将ifdef
魔法推送到make文件中,因此源代码保持尽可能干净。然后每个平台都有一个实现文件。这当然意味着您可以为所有支持的系统提供通用接口。
绕过这种较低分母设计进行跨平台开发的一种常见方法是不透明句柄习语。与ioctl(2)
转义路由相同的想法 - 让一个方法返回为每个平台(最好是在实现文件中)定义不同的不透明前向声明结构,并且仅在公共抽象不成立时才使用它。
答案 2 :(得分:2)
如果你完全确定你不会在编译的那个上使用其他操作系统的功能,那么使用ifdef有很多优点:
但是,基于操作系统的分类仍然可以带来好处:
后者是通过ifdefing类主体本身中的特定于平台的代码来实现的,或者只是在编译时定义不支持的OS实例。
答案 3 :(得分:2)
我的偏好是将平台特定问题推送到 leaf-most 模块,并尝试将它们包装到一个公共接口中。将特定的方法,类和函数放在单独的翻译单元中。让链接器和构建过程确定要组合的特定转换单元。这样可以实现更清晰的代码和更简单的调试时间。
根据经验,我有一个使用#ifdef VERSION2
的项目。我花了一周时间进行调试,因为一个模块使用了#ifdef VERSION_2
。如果所有版本2特定代码都在版本2模块中,那么更容易捕获的微妙之处。
答案 4 :(得分:0)
拥有特定于平台的代码的#ifdefs是惯用的;特别是因为如果一个平台的代码在另一个平台上启用,它甚至都不会编译。听起来对我很好。