IOS开始使用的编程语言主要是Objective-C,在大多数情况下可以满足我们的需求,但有些情况下,必须要用到C/C++语言:
①如很多算法都是以C/C++写成,如果要使用这些算法库,就会使用到C/C++
②C/C++语言的执行效率优于Objective-C,但系统对代码执行效率有很高要求时也需要使用C/C++
幸好,xcode支持C/C++,Objective-C混合编程。执行混合编程也很简单,只要注意将包含C++代码的.m文件改为.mm即可。但实际操作中还是很容易出现令人费解的编译问题,比如最经典的"Unknow type name ‘class’; did you mean ‘Class’?“。究其原因就是我们没有遵守这两条规则:
- .m文件不能含有C++代码
- .m文件所import或include的.h文件中不能直接或间接包含C++代码
比如,当你在AppDelegate.h中include或import一个C++的头文件时,当然你一定不会忘记修改AppDelegate.m为AppDelegate.mm,如果只做了这点儿还不够,我们还忽略了隐藏在Supporting Files组内的一个文件的存在–main.m,因为main.m包含有#import “AppDelegate.h",这就导致了main.m作为一个Objective-C源文件却引入了C++代码,而Xocde会使用Objective-C的编译器进行编译,从而产生编译错误,因此我们还需要将main.m的后缀改成.mm。
上面是比较特殊的情况,一般情况下,如果我们在A.m文件的头文件A.h中include或import一个C++,需要将此A.m文件改为A.mm文件;若是在另一文件B.m中include或import了A.h文件,也相当于间接include或import一个C++,也需要将B.m改为B.mm,否则就会编译出错。为了避免这种相互引入导致的间接引入C/C++,我们最好是将C++代码的头文件放在.mm文件而非其.h文件中,这样可以减少不注意的情况下出现类似错误。
在C/C++,Objective-C混合编程中,我们要特别注意Objective-C、C++的区别,可能一些细微的区别导致程序不能产生预期的结果,这种情况下还很难找到出现问题的原因。比如笔者曾遇到BOOL型变量的问题。在C++中BOOL型变量是True/False,其分别代表的是:非0值和0值,而在Objective-C中BOOL型变量是YES/NO,其分别代表的是1和0,当混合编译时True/False的值也变成了1和0。当时移植的算法源文件的作者编程习惯不好,返回类型是BOOL,但作为条件判断时是判断此BOOL类型值是否不等于1,结果直接导致逻辑错误。除了BOOL,还需注意其他标识符识id,Class,SEL,IMP。
OC方法内,编译器预声明了标识符self和super,就想C++中的关键字this。跟C++的this不同的是,self和super是上下文相关的;OC方法外他们还可以用于普通标识符。
Objective-C中没有NULL,用的是nil。nil是一个空对象,可以调用方法,不会crash。而NULL是一个值。
C/C++,Objective-C的相互调用关系,经过测试可以确定以下几点:
1. C++函数内可以调用OC方法、可以创建OC对象、函数参数可以为OC对象。
2. C++类的成员变量可以是OC对象。
3. 同样,OC也可以c++的语法,可以使用c++的方法和成员
4. 两者都可以直接调用C函数,只要包含了该C函数的实现
其实,在混编时,OC和C++的对象都是单纯的指针,所以可以任意的彼此调用对方的方法、使用对方的内部数据。但是,OC类与C++类无法相互继承,因为oc类的结构和c++类结构不同。