编写可移植代码时我应该记住哪些事项?因为我是一名c ++初学者,所以我想从一开始就练习它。
感谢。
答案 0 :(得分:17)
答案 1 :(得分:14)
将特定于平台的代码与可重用代码分开,最好是在不同的文件中,但至少在不同的函数中。如果您开始使用#if WIN32
以及#if CYGWIN
和#if BSD
,那么您将面临维护噩梦。
然后,尽早和经常在至少两个不同的平台上进行编译。典型的选择是Windows上的Visual C ++和Linux上的gcc。由于系统库和编译器都不是共享的,因此在它们在您的设计中根深蒂固之前,您将捕获非可移植代码。
答案 2 :(得分:13)
编写可移植代码时我应该记住哪些事项?
答案 3 :(得分:5)
答案 4 :(得分:4)
尽可能使用STL类型。请注意使用系统相关类型和API。例如,不要在Windows上使用类似UINT和DWORD的类型。
您可以使用类似boost的库,以便更轻松地编写可移植代码。如果您需要GUI,请考虑使用Qt等跨平台工具包。
有时您需要编写特定于平台的代码,在这种情况下,您可以执行以下操作:
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
答案 5 :(得分:2)
粗心的程序员可能会走进很多陷阱,我们可以尝试对其进行分类。但是让我先告诉你:绝对是不可能的。
问题在于,即使是符合标准的代码,由于特定的编译器问题,也可能无法移植。
现在,我可以在脑海中思考这些主要类别。
编译器扩展程序
例如使用变量数组:
void func(int const n)
{
int array[n];
}
这不是标准的,但许多编译器仍然支持它,因为它只是实用的。
标准库扩展
许多标准库实现提供了从未指定的std::hash_map
。如果您在代码中使用它,它就不可移植。
现代趋势是将这些内容存入std::tr1
命名空间,以便程序员知道这是一个扩展。
另请注意,许多人定义typedef
或非通用的宏(例如PRETTY_FUNCTION
)。标准没有指定宏,并且很少有typedef。
特定于平台
例如,标准中未指定int
或double
的大小和对齐方式。如果你做了一些比特,并期望它有32位,即使不改变你的编译器,你也会被困在64位平台上。
平台API
我们的程序需要编译,它们通常用于与运行的计算机进行交互:
您需要找到跨平台的便携式API,或者自己推送。检查下面列表中的一些库。
<强>库强>
大多数编写良好的库基本上都是可移植的,只需确保它们支持:
好的图书馆涉及:
您需要审核的其他人......这需要时间。
我认为那里没有完美的答案。但由于无法实现完美的可移植性,因此需要确定您希望支持的编译器和平台。
对于平台,您应该从Windows和一种Linux风格开始。对于编译器,选择任意两个(如果你能负担得起的话,请选择Comeau)。
答案 6 :(得分:2)
一些指导原则:
有时您必须权衡效率和性能以获得可移植性。例如,如果您的代码需要从缓冲区中访问字段,则始终可以将压缩结构转换为缓冲区指针。但这非常不便携。因此,您需要使用使用偏移量计算的命名指针 - 有时使用边界对齐处理代码。不漂亮,但便携。幸运的是,你可以通过明智地使用类接口来隐藏很多东西。
并非所有代码都需要以这种方式编写。如果您以非常模块化的方式设计应用程序,并且具有明确的责任范围,那么90-95%的代码可以轻松移植。然后在需要为新平台定制的非常本地化的区域中隔离5-10%。
答案 7 :(得分:2)
其他人之前说过,但这是我对此的看法:
1)你需要C ++吗?它不是编写可移植代码的最佳语言,因为它接近于裸机。 Java,Python,Perl,PHP或Javascript可能对您更好。
2)如果你需要C ++,不要试着写完全可移植的代码,无论如何这几乎是不可能的。相反,尽早决定要支持哪些平台。例如:Linux,MacOS X,Windows
3)确保连续测试所有选定平台上的代码。不要只是在Windows上构建,而是希望在“完成后”编译Linux版本。每天在所有平台上编译,并确保您继续测试它们是否存在问题。
答案 8 :(得分:1)
为了学习,尽量避免专注于一个实现的书籍。在某些情况下,介绍或早期章节将为您提供有关如何获取或使用语言实现的一些说明;如果它提到多个实现,你可能没问题。
获取与平台无关的参考书。 Stroustrup的 C ++编程语言是一个很好的参考,尽管对于初学者来说,尝试学习它并不是一本好书。不要依赖于给定实现的引用。例如,MSDN非常有用,但其主要关注点是如何使用Visual C ++编写Windows程序,而不是如何编写将在任何地方编译和运行的程序。
要编写任何真正有用的内容,您将不得不进入不可移植的代码。尝试养成将用户界面代码与其他所有内容分开的习惯,因为那时你的兼容性最低。您需要在平台之间更改的代码越少,代码的可移植性就越高。
答案 9 :(得分:1)
独立于操作系统的代码在C ++中非常难以实现。考虑一下这个简单的例子:
#include <iostream>
int main(int argc, char** argv) {
std::cout << argv[0] << std::endl;
}
这是完全有效的C ++,但它仍然不可移植,因为它不会接受Windows上的Unicode命令行参数。适用于Windows的正确版本为:
#include <iostream>
int wmain(int argc, wchar_t** argv) {
std::wcout << argv[0] << std::endl;
}
当然,这也是非便携式的,仅适用于Windows并且是非标准的。所以实际上你甚至不能在C ++中编写一个可移植的main()
函数而不需要求助于条件编译。
答案 10 :(得分:1)
如果可以的话,用至少两个不同的编译器编译所有代码。
答案 11 :(得分:0)
一个好主意是使用POSIX系统调用。这样您就不必处理创建线程或使用互斥锁和信号的不同方法。
问题是Windows并不完全符合POSIX标准,但有些库实现了某些POSIX功能,如下所示:[1]:http://sourceware.org/pthreads-win32/