这是我在C ++中编写任何稍微复杂的东西的第一次尝试,我正在尝试构建一个可以从Objective-C和.NET应用程序接口的共享库(好吧,那部分后来...... 。)
我的代码是 -
#ifdef TARGET_OS_MAC
// Mac Includes Here
#endif
#ifdef __linux__
// Linux Includes Here
#error Can't be compiled on Linux yet
#endif
#ifdef _WIN32 || _WIN64
// Windows Includes Here
#error Can't be compiled on Windows yet
#endif
#include <iostream>
using namespace std;
bool probe(){
#ifdef TARGET_OS_MAC
return probe_macosx();
#endif
#ifdef __linux__
return probe_linux();
#endif
#ifdef _WIN32 || _WIN64
return probe_win();
#endif
}
bool probe_win(){
// Windows Probe Code Here
return true;
}
int main(){
return 1;
}
我有一个编译器警告,只是untitled: In function ‘bool probe()’:untitled:29: warning: control reaches end of non-void function
- 但我也非常感谢人们可以建议如何更好地编写这类代码......
答案 0 :(得分:46)
而不是重复自己并再次写入相同的#ifdef ....行再次,你可能更好地在标题中声明probe()方法,并提供三个不同的源文件,一个用于每个平台。这样做的好处是,如果添加平台,则无需修改所有现有源,只需添加新文件即可。使用构建系统选择适当的源文件。
示例结构:
include/probe.h
src/arch/win32/probe.cpp
src/arch/linux/probe.cpp
src/arch/mac/probe.cpp
警告是因为probe()没有返回值。换句话说,三个#ifdef都不匹配。
答案 1 :(得分:32)
我将解决这个特定的功能:
bool probe() {
#ifdef TARGET_OS_MAC
return probe_macosx();
#elif defined __linux__
return probe_linux();
#elif defined _WIN32 || defined _WIN64
return probe_win();
#else
#error "unknown platform"
#endif
}
以if-elif-else链的方式编写它会消除错误,因为如果没有有效的return语句或命中#error就无法编译。
(我相信WIN32是针对32位和64位Windows定义的,但如果没有查找,我无法明确告诉你。这样可以简化代码。)
不幸的是,你不能使用#ifdef _WIN32 || _WIN64:请参阅http://codepad.org/3PArXCxo以获取示例错误消息。您可以使用特殊的仅预处理定义的运算符,如上所述。
关于根据功能或整个文件(如suggested)拆分平台,您可能想要也可能不希望这样做。它将取决于您的代码的详细信息,例如平台之间共享的内容以及您(或您的团队)最适合保持功能同步的内容,以及其他问题。
此外,您应该在构建系统中处理平台选择,但这并不意味着您不能使用预处理器:对每个平台使用有条件定义的宏(由makefile或构建系统定义)。实际上,这通常是模板和内联函数最实用的解决方案,这使得它比尝试消除预处理器更灵活。它与整个文件方法完美结合,因此您仍然可以在适当的地方使用它。
您可能希望使用单个配置标头,将所有各种特定于编译器和平台的宏转换为您控制的众所周知的宏。或者您可以通过构建系统将-DBEAKS_PLAT_LINUX添加到编译器命令行 - 以定义该宏(请记住使用宏名称的前缀)。
答案 2 :(得分:5)
在您编译代码时似乎没有定义TARGET_OS_MAC
,__linux__
,_WIN32
或_WIN64
。
所以它就像你的代码一样:
bool probe(){
}
这就是编译器抱怨到达非void函数结束的原因。没有return
条款。
此外,对于更一般的问题,这是我在开发多平台/架构软件/库时的指导原则:
避免特定情况。尝试编写与操作系统无关的代码。
在处理系统特定的东西时,尝试将东西包装成“不透明”的类。例如,如果您正在处理文件(Linux和Windows上的不同API),请尝试创建一个File
类,它将嵌入所有逻辑并提供通用接口,无论操作系统如何。如果其中一个操作系统上没有某个功能,请处理它:如果该功能对特定的操作系统没有意义,那么通常什么都不做。
简而言之:#ifdef
越少越好。无论您的代码多么可移植,请在发布之前在每个平台上进行测试。
答案 3 :(得分:1)
警告是因为如果实际上没有定义任何定义,那么探测函数中没有return
。对此的修复是默认的return
。
答案 4 :(得分:1)
除了上面的未完成选项之外,为了添加更多内容,编译器已知指令__linux__
和_WIN32
,其中TARGET_OS_MAC
指令不是,这可以是使用__APPLE__
解决。资料来源:http://www.winehq.org/pipermail/wine-patches/2003-July/006906.html