C++ vs Objective C

32 篇文章 0 订阅
22 篇文章 0 订阅
Are you a game developer transitioning from Cocos2d iPhone to Cocos2d-X? From Objective C to C++?

C++ used to be my language. It was all I wrote computer games in for over 10 years. There's a certain level of power, control and efficiency in using C++.

When the iPhone came out, the Objective C language became a hot topic. I was so excited about the thought of writing games for iPhone that I forced myself, despite wariness at [[funny foreign] syntax], to learn Objective C and begin writing a game. Boy was I surprised when I came to love Objective C's simple elegance and powerful Foundation classes.

Now, after nearly three years of making games in Objective C with Cocos2D-iPhone, I've discovered Cocos2D-X and unearthed a whole new love for C++.

C++ is a Manual Transmission Car

Tire Reflection If Objective C is an automatic transmission car, then C++ is a manual.

One might argue that the automatic car is superior because it's easier. However, that one hasn't had the experience of clutching into neutral across a gravelly patch to avoid spinning the tires.

So, C++ has more speed and control, yet it requires a greater level of skill from the programmer.

For example, C++ saves execution time by not checking pointers before you dereference them. This increases the speed of your game and your level of control, yet it requires basic assertion skills.

Sending Messages to nil Objects (or Dereferencing null Pointers)

Here we have one of the most fundamental differences between ObjC and C++.

With Objective C, you can safely send messages to nil objects (though this comes at the cost of slightly slower program execution).

// in Objective C
CCNode* node = nil;
 
// this will not crash, it will just do nothing
[node setPosition:ccp(10,10)];

In C++, if you try to dereference a null pointer, you'll trigger a runtime error and have to fix your code up.

// in C++
CCNode* node = nullptr; // nullptr introduced in C++11

// this will crash
node->setPosition(ccp(10,10));

// using a safeguard, this will not crash
if(node)
   node->setPosition(ccp(10,10));

// using an assertion will trigger a debuggable error
assert(node);
node->setPosition(ccp(10,10));

Behind the scenes, ObjC basically implements a nil object which essentially returns zero for any method call. This makes programming a little safer and easier. However, it also can allow bugs to go unnoticed.

Null pointer dereference C++ doesn't check a pointer before dereferencing it. As illustrated above, if the node is null, then C++ will execute the setPosition function given a null this pointer. When a member variable is accessed via the null this pointer, your program crashes.

One solution is to use an assert which only gets compiled into non-distribution builds. If the expression being asserted evaluates to false, then the program aborts. If you've got a debugger attached, then it will pause on the assert line so you can see exactly where the code went wrong.

CCNode* node = nullptr;

// this will pause execution when debugging
assert(node);

Since assert is typically defined as a macro, one of the pros to using it is that in distribution builds (or any build which defines NDEBUG), the macro evaluates to nothing. Essentially, the compiler doesn't even include it. This gives you the security of assertions in debug builds and the raw speed of no assertions in distribution builds.

Essentially this makes C++ a little more efficient and a bit easier to catch bugs at the cost of the programmer having to be a bit more pragmatic.

Readability

Here's another fundamental difference. Objective C is inherently more readable than C++ because method parameters are built into the name of the method. Consider:

// Objective C
[layer addChild:sprite z:1];
// C++
layer->addChild(sprite, 1);

You see the difference in readability?

Objective C is a bit easier to read because the 2nd parameter to the addChild method is clearly a z value. In C++, it's anyone's guess what "1" means.

Modern day Integrated Development Environments (IDEs) like Xcode mitigate the issue when you are writing code because of auto-completion. You start typing addChild and it gives you the parameter types and names. This makes it clear what the parameters are when you are writing the code. However, if you take some time off from the project and come back later, you might be a little perplexed when you glance at that addSprite call and wonder about the second parameter.

You can make C++ more readable by changing up your style a little bit. Like this:

int z = 1;
layer->addChild(sprite, z);

Speed and Portability

portability + protection We've already talked about how C++ is a faster than Objective C. But what about portability? This is where C++ shines.

C++ is simply more portable than Objective C. It can be natively compiled on many platforms including the presently popular Android OS.

When it comes to Android, it is technically possible to compile ObjC if you upgrade the default NDK's GCC compiler, but there's a catch or two. You need all those Foundation classes.

Remember NSObject, NSString and NSArray? Those are all implemented fully and awesomely on the Mac, but not Windows. All those have to be reimplemented in a cross-platform way.

Thankfully, there's projects like Cocotron which aim to do just that. However, when it comes down to areas that are Android-specific, like input and sound, you need a cross-platform library. Something that implements that stuff for you so you don't have to go rewriting it for each and every platform.

That's why C++ and Cocos2dx are so awesome. Cocos2dx handles the platform-specific stuff and does the bulk of it in portable C++.

Beyond speed, portability and readability, we get into more specific differences between the languages, like Objective C's Class and id types.

The Class and id Types

Objective C has a nifty thing called the Class type. It allows you to take the class of an object and store it in a variable.

C++ doesn't have the equivalent of a Class type. It does have runtime type information (RTTI) and can roughly convert a pointer into a string containing the object's class with typeid. However, since the results can vary per platform, the solution is not exact enough to be relied upon.

Objective C's Class type makes creating objects from strings quite nice. Consider the following:

// Objective C
NSString* string = @"Hammer";
Class class = NSClassFromString(string);
id object = [[class alloc] init];
// C++
Tool* tool = nullptr;
std::string string = "Hammer";
if( string == "Hammer" )
   tool = new Hammer;

This illustrates the elegance of ObjC's Class type and one possible workaround in C++.

You can also see in the above code we are using ObjC's id type. It is essentially a pointer to any object type. The rough equivalent in C++ is void*, however there are many reasons not to use either.

Laziness

Let's say we have a parent class called Parent, a subclass of it called Child, and Parent has a method called goToSleep.

In C++, you have to redefine goToSleep in Child's interface if you want to override. In Objective C, you can just be lazy and override it in the implementation.

// Objective C
@interface Parent : NSObject
   -(void) goToSleep;
@end

@interface Child : Parent
   // woo! don't have to redefine goToSleep
@end

@implementation Parent
   -(void) goToSleep {}
@end

@implementation Child
   -(void) goToSleep {}
@end
// C++
class Parent
{
   public:
      virtual void goToSleep();
};

class Child : public Parent
{
   public:
      // goToSleep has to be redefined
      // if it is to be overridden
      virtual void goToSleep();
};

void Parent::goToSleep() {}

void Child::goToSleep() {}

The reason C++ forces a programmer to redefine functions that will be overridden is because it makes the job of the compiler easier. The compiler doesn't have to go checking up the class hierarchy for mystery methods.

Virtual

Virtual Meeting Space In the above example, we saw the use of the C++ virtual keyword. When virtual is used, it specifies to use the function in the lowest class of the hierarchy first (for example Child's goToSleep as opposed to Parent's goToSleep).

In Objective C, all method calls are essentially virtual. This makes it a bit easier on the programmer, but it comes at a possible performance decrease.

Again, C++ comes through on the manual transmission car analogy. You can specify virtual or non-virtual, as appropriate.

The Stack

In Objective C, you can only allocate objects from the heap.

In C++, you can allocate objects on the stack. Stack allocation is faster than heap allocation and also guarantees that the destructor will be called when the object goes out of scope, even if an exception has been thrown.

Here's an example:

// Objective C
// Heap allocations only
Tool* tool = [[Tool alloc] init];
// C++
// Sweet! We've got fast, reliable stack allocations
Tool tool;

Operator Overloading

In C++ you can overload operators. For example, if you were programming a Vector object, you could overload the addition operator so that Vectors could naturally be added together.

// C++
class Vector
{
   const Vector operator+(const Vector& v) const
   {
      return Vector(x + v.x, y + v.y, z + v.z);
   }
}

// this '+' calls the overloaded operator+
// isn't it nice?
Vector v1,v2,v3;
v3 = v1 + v2;

In Objective C, it's not possible to overload operators. You can workaround that by creating worded methods:

// Objective C
v3 = [v1 addVector:v2];

However, this makes Objective C a bit wordy when it comes to some things:

// Objective C
NSString* a,*b;
if( [a isEqualToString:b] )
   [self doSomething];
// C++
std::string a,b;
if( a == b )
   doSomething();

Privates

Objective C doesn't technically have private methods. However, the workaround using a blank category in the implementation is quite nice because the private method doesn't have to be declared in the public interface (and hence your project automatically re-indexed because of a header file change):

// In an Objective C header file (.h)
@interface Something : NSObject
   // See? No private method
@end
// In the implementation file (.m)
// Extend the Something interface with a category
// (Blank categories denote private stuff)
@interface Something () // a blank category
   -(void) privateMethod;
@end

In C++, there is the concept of public and private, however the privates have to be declared in the public interface.

If you really don't want to declare a private function in the public interface, you can work around by using static functions in the implementation (which is similar to the Objective C blank category strategy mentioned above).

Class Extensions

As we saw in the above example, Objective C can extend a class with a category.

Categories are pretty neat because a class can be extended anywhere, including the .h, the .m or some other place.

C++ doesn't technically have the ability to extend a class. However, it does have multiple inheritance.

Default Parameters

C++ has one final bit of coolness to discuss: default parameters. A parameter to a function can be given a default, so that supplying it when calling the function is optional.

// C++
class Something
{
   void doSomething(int i, float f = 0.0f) {}
};

Something s;

// can be called with or without the f parameter
s.doSomething(5);
s.doSomething(5, 1.0f);

Objective C doesn't have default parameters, but it can get by with a multiple method workaround:

// Objective C
@interface Something : NSObject
   -(void) doSomething:(int)i;
   -(void) doSomething:(int)i withF:(float)f;
@end

@implementation Something
-(void) doSomething:(int)i
{
   [self doSomething:i withF:0.0f];
}

-(void) doSomething:(int)i withF:(float)f
{
}
@end

Something* s = [[Something alloc] init];

// either method can be called, however
// two separate methods have been implemented
[s doSomething:5];
[s doSomething:5 withF:1.0f];

Conclusion: Mixing C++ & ObjC

So that's about it for the primary differences between ObjC and C++.

Keep in mind that you can always use both. In fact, you can mix them together with Objective C++.

You just rename your implementation file with the .mm extension. That tells your compiler to use Objective C++ and enables either Objective C, C++ or a mix of both to be used.

// In the file AppDelegate.mm
@implementation AppDelegate
   -(void) applicationDidFinishLaunching:(NSNotification*)aNotification
   {
      // Do some Objective C stuff
      window = [[Window alloc] initWithContentRect:...];
      
      // Now switch to C++ and launch Cocos2dx
      cocos2d::CCApplication::sharedApplication().run();
   }
@end

Objective C++ is a common thing. As you can see in the example above, it's required to respond to iOS & Mac app notifications and launch Cocos2d-X in the same method.

Got questions? Leave a comment below.

Stay tuned. We are writing the next chapter in this free online book. If you'd like, you can subscribe to be notified when we release new chapters.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算法 4-5 增强for循环 4-6 数组和排序算法章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方法的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方法 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算法 4-5 增强for循环 4-6 数组和排序算法章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方法的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方法 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算法 4-5 增强for循环 4-6 数组和排序算法章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方法的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方法 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值