预处理程序指令的替代方案

ard*_*srk 6 c++ c-preprocessor

我正致力于在Symbian平台上开发C++手机应用程序.其中一个要求是它必须在所有Symbian手机上工作,从第2版手机到第5版手机.现在,跨版本的Symbian SDK存在差异.我必须使用预处理程序指令来有条件地编译与构建应用程序的SDK相关的代码,如下所示:

#ifdef S60_2nd_ED
  Code
#elif S60_3rd_ED
  Code
#else
  Code
Run Code Online (Sandbox Code Playgroud)

现在,由于我正在开发的应用程序并不简单,它很快就会增长到成千上万行代码,并且像上面那样的预处理程序指令将遍布各地.我想知道有没有替代方案,或者在这种情况下使用这些预处理器指令可能是更好的方法.

请帮忙.

unw*_*ind 16

嗯......这取决于差异的确切性质.如果可以将它们抽象出来并将它们分离成特定的类,那么你可以走这条路.这意味着具有某些类的特定于版本的实现,并且切换整个实现而不仅仅是几行.

你有

  • MyClass.h
  • MyClass_S60_2nd.cpp
  • MyClass_S60_3rd.cpp

等等.您可以选择要编译的CPP文件,方法是使用上面的#ifdefs包装整个内部,或者在构建级别(通过Makefile或其他)时控制在为各种目标构建时包含哪些文件.

根据变化的性质,这可能更清晰.

  • 这是最好的方法.使用构建系统来实现它的意义; `#ifdef`s是不可维护代码的路径. (3认同)

小智 6

在我们公司,我们编写了许多跨平台代码(win32/ps3/xbox/etc的游戏开发).
为了尽可能避免与平台相关的宏,我们通常使用接下来的几个技巧:

  • 将与平台相关的代码提取到平台抽象库中,这些库在不同平台上具有相同的接口,但实现并不相同;
  • 将代码拆分为不同平台的不同.cpp文件(例如:"pipe.h","pipe_common.cpp","pipe_linux.cpp","pipe_win32.cpp",...);
  • 使用宏和辅助函数来统一特定于平台的函数调用(例如:"#define usleep(X)Sleep((X)/ 1000u)");
  • 使用跨平台的第三方库.


Ste*_*sop 5

我一直都在你身边.

一个诀窍是,即使您在代码中有条件,也不要打开Symbian版本.这使得将来很难添加对新版本的支持,或者为某些方面不寻常的手机进行自定义.相反,确定您依赖的实际属性,围绕这些属性编写代码,然后包含一个头文件:

#if S60_3rd_ED
    #define CAF_AGENT 1
    #define HTTP_FILE_UPLOAD 1
#elif S60_2nd_ED
    #define CAF_AGENT 0
    #if S60_2nd_ED_FP2
        #define HTTP_FILE_UPLOAD 1
    #else
        #define HTTP_FILE_UPLOAD 0
    #endif
#endif
Run Code Online (Sandbox Code Playgroud)

等等.显然,如果您愿意,可以按功能而不是版本对定义进行分组,每个配置具有完全不同的标头,或者适合您的任何方案.

我们也为您继承的UI类定义了,因此在S60和UIQ之间存在一些共同的UI代码.事实上,由于产品是什么,我们没有太多与UI相关的代码,因此它的相当大比例很常见.

正如其他人所说,尽可能将变量行为放入类和函数中,并链接不同的版本更好.

[编辑回应评论:

我们努力避免做任何依赖于解决方案的事情 - 幸运的是特定的应用程序没有让这太难,所以我们有限的UI非常通用.我们打开屏幕分辨率的主要原因是飞溅/背景图像等.我们有一个脚本来预处理构建文件,它将宽度和高度替换为文件名,splash_240x320.bmp或其他.我们实际上手工生成了图像,因为没有那么多不同的尺寸,图像也没有经常变化.同一脚本生成一个.h文件,其中包含构建文件生成中使用的大多数值的#defines.

这适用于每个设备的构建:我们还有更多通用的SIS文件,它们只是动态调整图像大小,但我们经常对安装大小有要求(ROM有时非常有限,如果您的应用程序是基本设备映像的一部分,这很重要),调整图像大小是保持一点点的一种方法.为了支持N92,Z8等的屏幕旋转,我们仍然需要一些图像的纵向和横向版本,因为翻转宽高比不会像调整到相同或相似的比例那样提供良好的结果...]