前几天老师要求实现一个iphone上的“吃豆人”小游戏,给一下午加一晚上的时间。由于粟的设计很合理,且没有考虑太多、太复杂的情况(如 pacman 吃了 magic dot 后所有ghost的速度应该变慢),总体上没遇到什么太大的困难——只是在开发过程中曾遇到一个很诡异的错误:
为了遵循DRY原则,我把公用常量(ghost的数量)定义放在了一个define.h文件中,让大家都去import该文件。
当时我的常量定义是这样写的:
const int NUMOFGHOST = 4;
加完这句就出问题了,点击"build and run"按钮后报了一个错误,打开看后发现是一个从未见过的错误:
Command /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc-4.2 failed with exit code 1
当时感觉很不解,不知怎么加了这一句后gcc会非正常退出,由于时间比较紧就没有多想,直接改用宏定义了这个常量。
后来小游戏做得热火朝天(各种恶搞,给“吃豆人”加上了dota里的各种声音,背景音乐用的是亡灵序曲),也就忘了这个事了。
昨天看《高质量程序设计指南——C++/C语言》看到了C++与C中const关键字之不同时顿时想起了那个诡异的问题,同时也找到了答案。
书中说在标准C中const定义的变量是外连接的,即如果一个编译单元中定义了一个全局const常量,则其在其他编译单元中是可见的,如果其他编译单元也定义了同名const常量就会产生重复定义错误。这一点与C++不同,C++中const定义的变量是内连接的,即每个编译单元定义的全局const常量是自己独有的。
Objective-C是标准C的另一种扩展,那么我犯的错误也就很明显了——当多个编译单元都引用那个define.h文件时出现了重复定义错。
今天来到机房一试,果然如此,只要将
const int NUMOFGHOST = 4;
改为
static const int NUMOFGHOST = 4;
就顺利编译通过了。这里的static是用来把定义的const常量标记为对外不可见的。
这里顺便抱怨一句:这xcode也太不人性化了,重复定义就说重复定义嘛,非要用红红的字标出来"Command /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc-4.2 failed with exit code 1",反倒是很重要的那句"ld: duplicate symbol _NUMOFGHOST in /Users/asfgasiyf/Desktop/pacMan/build/pacMan.build/Debug-iphonesimulator/pacMan.build/Objects-normal/i386/MazeView.o and /Users/asfgasiyf/Desktop/pacMan/build/pacMan.build/Debug-iphonesimulator/pacMan.build/Objects-normal/i386/pacManAppDelegate.o"用灰灰的颜色显示,也不懂得突出一下重点⋯⋯