Using C++ With Objective-C
苹果的Objective-C编译器允许用户在同一个源文件里自由地混合使用C++和Objective-C,混编后的语言叫Objective-C++。有了它,你就可以在Objective-C应用程序中使用已有的C++类库。

Objective-C和C++混编的要点
在 Objective-C++中,可以用C++代码调用方法也可以从Objective-C调用方法。在这两种语言里对象都是指针,可以在任何地方使用。例 如,C++类可以使用Objective-C对象的指针作为数据成员,Objective-C类也可以有C++对象指针做实例变量。下例说明了这一点。
注意:Xcode需要源文件以".mm"为扩展名,这样才能启动编译器的Objective-C++扩展。

  1. /* Hello.mm
  2. * Compile with: g++ -x objective-c++ -framework Foundation Hello.mm  -o hello
  3. */
  4. #import <Foundation/Foundation.h>
  5. class Hello {
  6. private:
  7. id greeting_text;  // holds an NSString
  8. public:
  9. Hello() {
  10. greeting_text = @"Hello, world!";
  11. }
  12. Hello(const char* initial_greeting_text) {
  13. greeting_text = [[NSString alloc] initWithUTF8String:initial_greeting_text];
  14. }
  15. void say_hello() {
  16. printf("%s/n", [greeting_text UTF8String]);
  17. }
  18. };
  19. @interface Greeting : NSObject {
  20. @private
  21. Hello *hello;
  22. }
  23. - (id)init;
  24. - (void)dealloc;
  25. - (void)sayGreeting;
  26. - (void)sayGreeting:(Hello*)greeting;
  27. @end
  28. @implementation Greeting
  29. - (id)init {
  30. if (self = [super init]) {
  31. hello = new Hello();
  32. }
  33. return self;
  34. }
  35. - (void)dealloc {
  36. delete hello;
  37. [super dealloc];
  38. }
  39. - (void)sayGreeting {
  40. hello->say_hello();
  41. }
  42. - (void)sayGreeting:(Hello*)greeting {
  43. greeting->say_hello();
  44. }
  45. @end
  46. int main() {
  47. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  48. Greeting *greeting = [[Greeting alloc] init];
  49. [greeting sayGreeting];                         // > Hello,  world!
  50. Hello *hello = new Hello("Bonjour, monde!");
  51. [greeting sayGreeting:hello];                   // > Bonjour,  monde!
  52. delete hello;
  53. [greeting release];
  54. [pool release];
  55. return 0;
  56. }

正如你可以在OC接口中声明C结构一样,你也可以在OC接口中声明C++类。跟C结构一样,OC接口中定义的C++类是全局范围的,不是OC类的内嵌类(这与标准C(尽管不是C++)提升嵌套结构定义为文件范围是一致的)。
为了允许你基于语言变种条件化地编写代码,OC++编译器定义了__cplusplus和__OBJC__预处理器常量,分别指定C++和OC。    如前所述,OC++不允许C++类继承自OC对象,也不允许OC类继承自C++对象。

  1. class Base { /* ... */ };
  2. @interface ObjCClass: Base ... @end // ERROR!
  3. class Derived: public ObjCClass ... // ERROR!

与 OC不同的是,C++对象是静态类型的,有运行时多态是特殊情况。两种语言的对象模型因此不能直接兼容。更根本的,OC和C++对象在内存中的布局是互不 相容的,也就是说,一般不可能创建一个对象实例从两种语言的角度来看都是有效的。因此,两种类型层次结构不能被混合。
你可以在OC类内部声明C++类,编译器把这些类当作已声明在全局名称空间来对待。就像下面:

  1. @interface Foo {
  2. class Bar { ... } // OK
  3. }
  4. @end
  5. Bar *barPtr; // OK

OC允许C结构作为实例变量,不管它是否声明在OC声明内部。

  1. @interface Foo {
  2. struct CStruct { ... };
  3. struct CStruct bigIvar; // OK
  4. } ... @end

Mac OS X 10.4以后,如果你设置fobjc- call-cxx-cdtors编译器标志,你就可以使用包含虚函数和有意义的用户自定义零参数构造函数、析构函数的C++类实例来做为实例变量 (gcc-4.2默认设置编译器标志fobjc-call-cpp-cdtors)。OC成员变量alloc完以后,alloc函数会按声明顺序调用构造 器。构造器使用公共无参数恰当的构造函数。OC成员变量dealloc之前,dealloc方法按声明顺序反序调用调用析构函数。    OC没有名称空间得概念。不能在C++名称空间内部声明OC类,也不能在OC类里声明名称空间。
OC类,协议,分类不能声明在C++ template里,C++ template也不能声明在OC接口,协议,分类的范围内。
但是,OC类可以做C++ template的参数,C++ template参数也可以做OC消息表达式的接收者或参数(不能通过selector)。

C++词汇歧义和冲突
OC头文件中定义了一些标识符,所有的OC程序必须包含的,这些标识符识id,Class,SEL,IMP和BOOL。
OC方法内,编译器预声明了标识符self和super,就想C++中的关键字this。跟C++的this不同的是,self和super是上下文相关的;OC方法外他们还可以用于普通标识符。
协议内方法的参数列表,有5个上下文相关的关键字(oneway,in,out,inout,bycopy)。这些在其他内容中不是关键字。
从 OC程序员的角度来看,C++增加了不少新的关键字。你仍然可以使用C++的关键字做OC selector的一部分,所以影响并不严重,但你不能使用他们命名OC类和实例变量。例如,尽管class是C++的关键字,但是你仍然能够使用 NSObject的方法class:

  1. [foo class]; // OK

然而,因为它是一个关键字,你不能用class做变量名称:

  1. NSObject *class; // Error

OC里类名和分类名有单独的命名空间。@interface foo和@interface(foo)能够同时存在在一个源代码中。OC++里,你也能用C++中的类名或结构名来命名你的分类。
协议和template标识符使用语法相同但目的不同:

  1. id<someProtocolName> foo;
  2. TemplateType<SomeTypeName> bar;

为了避免这种含糊之处,编译器不允许把id做template名称。    最后,C++有一个语法歧义,当一个label后面跟了一个表达式表示一个全局名称时,就像下面:

  1. label: ::global_name = 3;

第一个冒号后面需要空格。OC++有类似情况,也需要一个空格:

  1. receiver selector: ::global_c++_name;

限制
OC++ 没有为OC类增加C++的功能,也没有为C++类增加OC的功能。例如,你不能用OC语法调用C++对象,也不能为OC对象增加构造函数和析构函数,也不 能将this和self互相替换使用。类的体系结构是独立的。C++类不能继承OC类,OC类也不能继承C++类。另外,多语言异常处理是不支持的。也就 是说,一个OC抛出的异常不能被C++代码捕获,反过来C++代码抛出的异常不能被OC代码捕获。

最新文章

  1. 移居 GitHub
  2. 谈谈asp.net MVC中的AppendTrailingSlash以及LowercaseUrls ,你还记得吗?
  3. 理解 JavaScript 作用域和作用域链
  4. Android EditText输入格式设置
  5. myIsEqualToString
  6. Eclispe怎么给工作空间下的项目分组
  7. VS2008的DLL项目添加了方法但是找不到怎么办?
  8. poj1420 拓扑序
  9. Java最重要的21个技术点和知识点之JAVA集合框架、异常类、IO
  10. JavaScript如何获取css属性
  11. shell之sort
  12. 沃森Mysql数据库修复工具
  13. 问题 : lang.NoClassDefFoundError: org/springframework/core/annotation/AnnotatedElementUtils,的解决方法
  14. 201521123104 《Java程序设计》 第10周学习总结
  15. Java 常用单词
  16. 第十三章:UNDO段
  17. linux18.04下安装的jdk11.0.2
  18. Discuz!安装搭建
  19. c#代码 天气接口 一分钟搞懂你的博客为什么没人看 看完python这段爬虫代码,java流泪了c#沉默了 图片二进制转换与存入数据库相关 C#7.0--引用返回值和引用局部变量 JS直接调用C#后台方法(ajax调用) Linq To Json SqlServer 递归查询
  20. web基础----&gt;okhttp的使用

热门文章

  1. intellij ide 激活(转发)
  2. 剑指offer:构建乘积数组
  3. Redis和MongoDB的区别以及应用场景
  4. linux系统备份恢复到本机或是别的机器上
  5. ES6将两个数组合并成一个对象数组
  6. Partition-wise join
  7. Oracle的ole db连接字符串
  8. [LeetCode] 655. Print Binary Tree 打印二叉树
  9. [LeetCode] 857. Minimum Cost to Hire K Workers 雇K个工人的最小花费
  10. LeetCode:复原IP地址【93】