从C到ObjectiveC类和对象续修订稿

合集下载

第二、三章objective-c类和对象PPT教学课件

第二、三章objective-c类和对象PPT教学课件

8
显示变量的值
NSlong不仅能显示简单的短语,还能显示变量的值以及计算的结果。 显示两个数相加的结果:
#import <Foundtion/Foundtion.h>
int main(int argc, const * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc]init];
int n1,n2,sum;
n1 = 30;
n2 = 432
sum = n1 + n2;
第二章 Objective-c程序 设计
2020/12/10
1
第一个程序:Hello Word!
//First program example #import <Foundtion/Foundtion.h> int main(int argc, const * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc]init]; NSlog(@”Hello Word!”); [pool drain]; return 0; } 在Objective-C中,大小写字母是不同的。 1//First program example 注释。增强程序的可读性和维护性。 2//表示注释到这行结尾的任何字符都被编译器忽略。 3/* */表示在此区间的任何字符都被看成注释语句的一部分。不能嵌套 使用
何处开始执行
2020/12/10
4
第一个程序:Hello Word!
//First program example #import <Foundtion/Foundtion.h> int main(int argc, const * argv[]) {

最新Object-OrientedProgramminginC++第二章类和对象

最新Object-OrientedProgramminginC++第二章类和对象
对象定义示例 如前例中,声明了一个名为 rectangle 的类,我们可以定义该
类的若干对象: rectangle r1, r2, r3;
对象定义说明 类的声明和对象的定义可以想结构体类型声明和结构体变量定
义一样,合在一起完成。请同学们自己阅读教材48页的内容。
C++
2- 15
2.3 类的成员函数
C++
2- 12
2.2 类的声明和对象的定义
类的声明
类的声明方法和结构体的声明方法一样,只是将关键字
struct 换成class:
class 类名
成员访问限定符
{ private:
( member access specifier )
私有数据成员和私有成员函数;
public:
成员访问限定符
公共数据成员和公共成员函数; ( member access specifier )
C++中,对象的类型称为类( class )。类代表了某一批对 象的共同特性。前面已经谈到,类是对象的抽象,而对象是类 的具体实例( instance )。就象结构体类型和结构体变量一样。
C++中,我们先声明一个类的类型,然后再定义该类的若 干对象。对象就是类这种类型的一个变量。类是抽象的,不占 内存,而对象是具体的,要占用内存空间。
class rectangle { private:
int length, width,; int area, perimeter ; public: void PutArea ( ); void PutPerimeter ( ); void display ( ); }; void rectangle:: PutArea ( ) { area = length * width;}

Objective_C 与C的不同

Objective_C   与C的不同

与C语言相比要注意的地方:1. 文件介绍:Objective-C 也使用头文件(header files),后缀为 .h, 但使用 .m(即 message, 其他面向对象编程语言也叫 method),作为源文件的后缀。

在objective-c中使用#import<>,而不使用#include<>,#import可以保证头文件只被包含一次。

2. 与C一致的地方:数据类型,表达式,各种运算符循环:for, while, do while, break, continue分支:if, else, switch3. NSlog()函数:与printf()类似,想控制台输出信息。

但它增加了一些特性,如时间戳等。

【cocoa对起所有的函数,常量和类型名称都添加了NS前缀。

】4. 双引号的前面的@表示这双引号中的字符串应该作为cocoa的NSString元素来处理。

5. 布尔类型BOOL:值为YES,NO;6. %d表示输出整数%@表示输出NSString类型%s表示输出字符串数组(char*);7. objective-c中的方括号:1. 用于通知某个对象该做什么。

2. 方括号内第一项是对象,其余部分是你需要对象执行的操作。

3. 在objective-c中通知对象执行某种操作,称为发送消息。

(也叫调用方法)8. 标识符id:是一种泛型,用于表示任何种类的对象。

9. 类声明@interface:@interface Circle:NSObject //为Circle类定义接口;NSObject表示是父类。

{//以下是数据成员ShapeColor fillColor;ShapeRect bounds;}//以下是方法声明-(void) setFillColor: (ShapeColor) fillColor; //前面的短线表明这是方法声明//短线后面是方法的返回类型//接着是方法名//冒号后面是参数,其中(ShapeColor)是参数类型,fillColor是参数名-(void) setBounds:(ShapeRect) bounds;-(void) draw;//减号就是普通函数加号就是静态函数@end //结束声明objective-c看到@符号,就把它看成是C语言的扩展。

面向对象 发展历程

面向对象 发展历程

面向对象发展历程面向对象编程(Object-Oriented Programming,简称OOP)是一种软件开发方法,它以对象作为程序的基本单位,将数据和操作封装在一起,实现了数据的抽象、封装、继承和多态等特性。

面向对象的发展历程可以追溯到20世纪70年代,以下是面向对象发展的一些重要里程碑:1. Simula语言(1967年):Simula是第一个支持面向对象编程的语言,它是由挪威计算机科学家Ole-Johan Dahl和Kristen Nygaard开发的。

Simula引入了类和对象的概念,并提供了一些面向对象的关键特性,如继承和多态。

2. Smalltalk语言(1972年):Smalltalk是第一门完全面向对象的编程语言,它由Xerox PARC实验室的Alan Kay等人开发。

Smalltalk引入了封装、消息传递和动态绑定等概念,对后续的面向对象语言设计产生了重要影响。

3. C++语言(1983年):C++是一种面向对象的扩展C语言,由Bjarne Stroustrup开发。

C++在C语言的基础上引入了类、对象、继承、多态等特性,成为当今广泛应用的高级编程语言之一。

4. Objective-C语言(1984年):Objective-C是一种面向对象的扩展C语言,由Brad Cox和Tom Love开发。

Objective-C与C++类似,支持类、对象、继承等特性,但它更加动态灵活,被广泛用于苹果公司的iOS和macOS开发。

5. Java语言(1995年):Java是一种面向对象的编程语言,由Sun Microsystems的James Gosling等人开发。

Java继承了C++的面向对象特性,但去除了一些复杂和容易出错的特性,比如操作符重载和多重继承,提供了更安全、可靠的软件开发环境。

6. C#语言(2000年):C#是一种面向对象的编程语言,由Microsoft公司开发。

C#在语法上类似于Java,但引入了许多新的特性,如委托、属性和事件等,提供了更强大和灵活的开发工具。

Objective-C类方法与对象方法、区别、与调用

Objective-C类方法与对象方法、区别、与调用

Objective-C类⽅法与对象⽅法、区别、与调⽤类⽅法.1. 特点:以加号( + )开头,调⽤格式: [类名⽅法名]类⽅法的好处:不需要创建实例对象,直接通过类名访问,节省空间,提⾼了效率2.注意事项:类⽅法可以和实例⽅法同名, 相互之间互不影响类⽅法可以从⽗类继承⽽来,⼦类可以重写类⽅法 // ,如description类⽅法类⽅法和实例⽅法⼀样在interface⾥声明, 在implementation⾥实现。

类⽅法由类名调⽤, 实例⽅法由对象调⽤。

在类⽅法⾥使⽤了self, self指代的是调⽤者类在类⽅法中不能使⽤类的成员变量类⽅法和对象⽅法之间不能使⽤self 相互调⽤总结self : 谁调⽤当前⽅法, self就代表谁3.对象⽅法中可以调⽤其他对象⽅法1)当前对象⽅法中创建对象(可以是当前类的实例对象,也可以是其他类的实例对象),使⽤新创建的对象调⽤⽅法2)可以使⽤self3)对象作为⽅法的参数传递过来,可以使⽤传递过来的对象调⽤⽅法4.在类⽅法中可以调⽤其他类的⽅法1)可以直接使⽤类名(或者其他类名)调⽤类⽅法2)可以使⽤self5) 在类⽅法中可以调⽤对象⽅法1)对象作为⽅法的参数传递过来2)可以创建⼀个对象6.类⽅法和对象⽅法的⽐较对象⽅法以减号开头, 可以使⽤成员变量类⽅法以加号开头,不能使⽤成员变量7.类⽅法使⽤场景如果我们调⽤⼀个⽅法,该⽅法中不需要使⽤成员变量,那么我们可以将该⽅法声明为类⽅法以下代码是对上述部分知识点的验证main.m#import <Foundation/Foundation.h>#import "Dog.h"int main(int argc, const char * argv[]) {@autoreleasepool {// 1. 通过类名调⽤eat类⽅法[Dog eat];// 2. 调⽤jump类⽅法Dog *dog = [Dog new];[Dog jump:dog];// [dog bark];}return 0;}Dog.h#import <Foundation/Foundation.h>@interface Dog : NSObject//类⽅法和实例⽅法⼀样在interface⾥声明。

从 C++ 到 OBJECTIVE C(3):类和对象

从 C++ 到 OBJECTIVE C(3):类和对象

从C++到Objective-C(3):类和对象作者:DevBean日期:2011年03月19日发表评论(5)查看评论既然是面向对象语言,类和对象显然是应该优先考虑的内容。

鉴于本系列已经假定你已经熟悉C++语言,自然就不会去解释类和对象的含义。

我们直接从Objecti-C和C++的区别开始说起。

Objetive-C使用的是严格的对象模型,相比之下,C++的对象模型则更为松散。

例如,在Objective-C中,所有的类都是对象,并且可以被动态管理:也就是说,你可以在运行时增加新的类,根据类的名字实例化一个类,以及调用类的方法。

这比C++的RTTI更加强大,而后者只不过是为一个“static”的语言增加的一点点功能而已。

C++的RTTI在很多情况下是不被推荐使用的,因为它过于依赖编译器的实现,牺牲了跨平台的能力。

根类,id类型,nil和Nil的值任何一个面向对象的语言都要管理很多类。

同Java类似,Objective-C有一个根类,所有的类都应该继承自这个根类(值得注意的是,在Java中,你声明一个类而不去显式指定它继承的父类,那么这个类就是Object类的直接子类;然而,在Objective-C中,单根类的子类必须被显式地说明);而C++并没有这么一个类。

Cocoa中,这个根类就是NSObject,它提供了很多运行时所必须的能力,例如内存分配等等。

另外需要说明一点,单根类并不是Objective-C语言规范要求的,它只不过是根据面向对象理论实现的。

因此,所有Java虚拟机的实现,这个单根类都是Object,但是在Objective-C中,这就是与类库相关的了:在Cocoa中,这个单根类是NSObject,而在gcc的实现里则是Object。

严格说来,每一个类都应该是NSObject的子类(相比之下,Java应该说,每一个类都必须是Object的子类),因此使用NSObject*类型应该可以指到所有类对象的指针。

c讲稿Chapter2-类和对象

c讲稿Chapter2-类和对象
3
本章内容
2.1 面向对象程序设计方法概述
2.2 类的定义 2.3 对象的定义 2.4 对象成员的引用 2.5 类和对象的简单应用举例 2.6 类的封装性和信息隐蔽
4
2.1 面向对象程序设计方法概述
2.1.1 什么是面向对象的程序设计
(一)面向过程程序设计
程序的主 体是函数
5
2.1 面向对象程序设计方法概述
2.3 对象的定义 2.4 对象成员的引用 2.5 类和对象的简单应用举例 2.6 类的封装性和信息隐蔽
16
2.2 类的定义
2.2.2 类的定义
(一)定义格式
class 类名 { private:
私有数据成员和成员函数; public:
公有数据成员和成员函数; protected:
保护数据成员和成员函数;
20
2、定义表示学生的类——Student
class Student { private:
int num; string name; char sex; …… };
//学号 //姓名 //性别
21
2.2 类的定义
2.2.3 类的数据成员
定义格式 数据类型 成员名;
其中: 数据类型可是是基本数据类型,也可以是构
12
2.1 面向对象程序设计方法概述
2.1.2 面向对象的程序设计的基本概念
(二)类
一组具有相同特征的对象的属性和方法的描述就 称为类。
例如: 输入圆的半径,计算圆的周长和面积
面向对象程序设计方法实现
13
2.1 面向对象程序设计方法概述
2.1.2 面向对象的程序设计的基本概念
(三)面向对象程序设计的三大特性 1、封装性 2、继承性 3、多态性

c语言类和对象的定义

c语言类和对象的定义

c语言类和对象的定义C语言中的类和对象定义在C语言中,类和对象是用来组织和管理代码的重要工具。

虽然C 语言并没有像C++或Java一样提供内置的类和对象机制,但我们仍然可以通过一些技巧来实现类似的功能。

1. 什么是类和对象?类是一种用户自定义的数据类型,它可以包含多个成员变量和成员函数。

对象是类的一个实例,通过创建对象可以使用类中定义的成员变量和成员函数。

2. 如何定义类?在C语言中,我们可以使用结构体来定义类。

结构体是一种可以存储不同类型的数据的数据类型,它可以包含多个成员变量。

例如,我们可以定义一个表示学生的类:```cstruct Student {char name[20];int age;float score;};```上述代码定义了一个名为Student的结构体,它包含了三个成员变量:name、age和score,分别表示学生的姓名、年龄和分数。

3. 如何创建对象?在C语言中,我们可以通过声明结构体变量来创建对象。

通过使用结构体变量名和点操作符,我们可以访问和修改对象的成员变量。

例如,我们可以创建一个名为stu的学生对象,并对其成员变量进行赋值:```cstruct Student stu;strcpy(, "Tom");stu.age = 18;stu.score = 90.5;```上述代码创建了一个名为stu的学生对象,并将其姓名设置为"Tom",年龄设置为18,分数设置为90.5。

4. 如何定义对象的行为?在C语言中,我们可以通过函数来定义对象的行为,这些函数可以操作对象的成员变量,实现一些特定的功能。

例如,我们可以定义一个函数来计算学生的平均分数:```cfloat calculateAverage(struct Student stu) {return stu.score / 3;}```上述代码定义了一个名为calculateAverage的函数,它接受一个学生对象作为参数,并返回该学生的平均分数。

第二章、objective-c类和对象

第二章、objective-c类和对象
#import <Foundation/Foundation.h> @interface Fraction : NSObject { int numerator;//实例变量的声明 实例变量的声明 int denominator; } -(void) print;//方法的声明 方法的声明 -(void) setNumerator: (int) n; -(void) setDenominator: (int) d; @end
只需修改一处
间接(cont.)
文件与间接
假设要修改字符 串不得不修改源 代码
#import <Foundation/Foundation.h> int main(int argc, const char char *argv[]) { Int wordCount = 2; const char *words[wordCount] = {"aardvark", "abacus"}; Int i; for(i=0; i<wordCount; i++) { NSLog(@"%s is %d is %d characters long", words[i], strlen(words[i])); } return (0); }
Fraction类(cont.)
类,实例变量,和方法的实现
@implementation 类名 方法的实现 @end
#import "fraction.h" @implementation Fraction -(void) print { NSLog( @"%i/%i", numerator, denominator ); } -(void) setNumerator: (int) n { numerator = n; } -(void) setDenominator: (int) d { denominator = d; } @end

突破Objective-C开发速学手册之面向对象编程

突破Objective-C开发速学手册之面向对象编程

.调用出现在=号的左 边,相当于setter
.调用出现在=号右 边,相当于getter
52
.
6.4.3 带参属性——setter/getter 方法(assign/retain/copy)
赋值方法 assign retain copy
作用 为变量赋值 释放旧的对象,将旧对象的值赋予输入对象。实 际上是将复杂的类型复制。
... }
-/+(方法的返回值类型) 方法名;
@end
方法的声明
28
.
6.3.2 方法的实现
实现方法是指在方法的定义中编写该方法 的代码,确定该方法实现的功能。所以, 需要在***.m中编写方法的代码。
#import "类名.h" @implementation 类名 -/+ (方法的返回值类型) 方法名 {
21
.
2.extern
数据类型可 以省去 extern 数据类型 变量列表;
22
.
3.auto
auto用于声明一个自动的局部变量,是方法 内部变量的声明方式,是缺省设置。一般 我们都会将其省却。
auto 数据类型 变量列表;
23
.
3.auto
auto int x;
等价于
int x;
24
.
4.const
... }
-/+(方法的返回值类型) 方法名:(参数类型) 参数名;
@end
单个参数方法的声明
37
.
1.一个参数的方法
#import "类名.h" @implementation 类名 -/+ (方法的返回值类型) 方法名:(参数类型) 参数名 {

Objective-C类别(category)和扩展(Extension)

Objective-C类别(category)和扩展(Extension)

Objective-C类别(category)和扩展(Extension)1、类别(category)使⽤Object-C中的分类,是⼀种编译时的⼿段,允许我们通过给⼀个类添加⽅法来扩充它(但是通过category不能添加新的实例变量),并且我们不需要访问类中的代码就可以做到,这点和javascript中使⽤原型来定义属性有点类似。

我们可以为⼀个类创建⼀个新的⽅法,⽽不需要在代码中编辑类定义。

下⾯就是定义并使⽤分类的例⼦程序,通过下⾯代码,我们可以给Object-C中的NSString 添加camelCaseString分类,使⽤camelCaseString⽅法,就可以去掉⼀个字符串中的空格,并将原有空格后的单词改写成⼤写(即将字符串转化为驼峰式)。

#import <Foundation/Foundation.h>/*定义分类的过程⼤致可分为以下⼏个步骤:第⼀步、创建⼀个带有接⼝的新⽂件,即创建已有类第⼆步、在新⽂件中添加需要扩展的⽅法及⽅法的实现,即需要添加的分类*///NSString 表⽰将要添加分类的类名称,该类必须是已存在的。

//CamelCase 是为类添加的⽅法名称。

//只能添加⽅法,不能添加变量。

//头⽂件命名惯例:ClassName+CategoryName.h@interface NSString (CamelCase)-(NSString*) camelCaseString;@end@implementation NSString (CamelCase)-(NSString*) camelCaseString{//调⽤NSString的内部⽅法获取驼峰字符串。

//self指向被添加分类的类。

NSString *castr = [self capitalizedString];//创建数组来过滤掉空格, 通过分隔符对字符进⾏组合。

NSArray *array = [castr componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];//把数组的字符输出NSString *output = @"";for(NSString *word in array){output = [output stringByAppendingString:word];}return output;}@endint main (int argc, const char * argv[]){NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];NSString *str = @"My name is bill.";NSLog(@"%@", str);str = [str camelCaseString];NSLog(@"%@", str);[pool drain];return 0;}2、扩展(Extension)你可以这样理解:扩展就是匿名分类,下⾯是⼀个扩展的例⼦:@interface MyClass : NSObject- (float)value;@end@interface MyClass () { //注意此处:扩展 float value;}- (void)setValue:(float)newValue;@end@implementation MyClass- (float)value {return value;}- (void)setValue:(float)newValue {value = newValue;}@end。

objective c类方法

objective c类方法

objective c类方法Objective-C是一种面向对象的编程语言,广泛应用于iOS和macOS开发中。

在Objective-C 中,类方法(Class Method)是指属于类本身而不是类的实例的方法。

类方法可以直接通过类名调用,不需要先创建类的对象。

本文将详细介绍Objective-C的类方法,包括其定义、调用、特点、应用场景等方面。

一、类方法的定义Objective-C中的类方法是在类的实现文件(.m文件)中定义的,使用"+"符号表示。

通常在类的接口文件(.h文件)中会声明类方法的原型,在实现文件中实现。

例如,下面是一个简单的类方法的定义:+ (void)printHello {NSLog(@"Hello, World!");以上代码中,`printHello`是一个类方法,无返回值(`void`),用于在控制台输出"Hello, World!"。

二、类方法的调用类方法可以通过类名直接调用,不需要先创建类的对象。

调用类方法的格式为:[类名方法名]。

例如,使用上述示例中的类方法进行调用:[ClassName printHello];其中,`ClassName`是类的名称,`printHello`是方法的名称。

三、类方法的特点1. 类方法属于类本身而不是实例对象,因此可以直接通过类名调用。

2. 类方法可以直接访问类的静态变量,不需要先创建类的对象。

3. 类方法不能直接访问实例变量,因为类方法不依赖于实例。

4. 类方法在整个程序运行期间保持不变,可以被多个实例对象共享使用。

为了更好地理解类方法的特点,我们以一个计算圆的面积和周长的例子进行说明。

首先,创建一个名为Circle的类,类中定义了一个类方法`calculateAreaWithRadius:`用于计算圆的面积。

@interface Circle : NSObject+ (CGFloat)calculateAreaWithRadius:(CGFloat)radius;在实现文件中,我们通过使用类方法进行圆的面积计算:@implementation Circle+ (CGFloat)calculateAreaWithRadius:(CGFloat)radius {return M_PI * radius * radius;然后,我们可以在其他地方直接使用该类方法,而无需先创建圆的对象。

objective c 类方法

objective c 类方法

objective c 类方法Objective-C是一种面向对象的编程语言,它支持类方法和实例方法。

类方法是指只能由类本身调用的方法,而不是由类的实例调用的方法。

在Objective-C中,类方法使用"+"符号来声明和实现。

类方法的格式如下:```+ (返回类型)方法名:(参数类型)参数名 {// 方法实现代码}```类方法可以在没有实例的情况下调用,并且在整个应用程序中只存在一个副本,因此它们常用于实现单例模式、全局共享的方法等。

下面我将介绍一些关于Objective-C类方法的常见用法和最佳实践。

1. 创建单例模式类方法被广泛用于创建单例模式的实例。

在单例模式中,一个类只能创建一个唯一的实例,并提供一个全局访问点。

通常的实现方式是在类方法中创建实例,并将其存储为静态变量,确保它只被创建一次。

```objective-c+ (instancetype)sharedInstance {static MyClass *sharedInstance = nil;static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{sharedInstance = [[MyClass alloc] init];});return sharedInstance;}```在这个例子中,类方法`sharedInstance`通过`dispatch_once`确保只有一个线程能够创建实例,并使用静态变量来存储唯一的实例。

2. 计算类级别的属性类方法也可以用于计算类级别的属性。

例如,我们想要在整个应用程序中跟踪某个类的实例数量,我们可以使用类方法来实现一个静态变量来计数实例的数量。

```objective-c+ (NSInteger)instanceCount {static NSInteger count = 0;return count;}+ (instancetype)newInstance {MyClass *instance = [[MyClass alloc] init];[self setInstanceCount:[self instanceCount] + 1];return instance;}```在这个例子中,类方法`newInstance`创建一个新的实例,并通过`setInstanceCount`方法增加实例计数。

从 C++ 到 Objective-C(4):类和对象(续)

从 C++ 到 Objective-C(4):类和对象(续)

从C++ 到Objective-C(4):类和对象(续)作者:?DevBean?日期: 2011 年03 月19 日发表评论?(9)查看评论方法Objective-C 中的方法与C++ 的函数在语法方面风格迥异。

下面,我们就来讲述Objective-C 的方法。

原型、调用、实例方法和类方法∙以–开头的是实例方法(多数情况下都应该是实例方法);以+ 开头的是类方法(相当于C++ 里面的static 函数)。

Objective-C 的方法都是public 的;∙返回值和参数的类型都需要用小括号括起来;∙参数之间使用冒号:分隔;∙参数可以与一个标签label 关联起来,所谓标签,就是在: 之前的一个名字。

标签被认为是方法名字的一部分。

这使得方法比函数更易读。

事实上,我们应该始终使用标签。

注意,第一个参数没有标签,通常它的标签就是指的方法名;∙方法名可以与属性名相同,这使getter 方法变得很简单。

C++// 原型void Array::insertObject(void*anObject, unsigned int atIndex);// shelf 是 Array 类的一个实例,book 是一个对象shelf.insertObject(book, 2);Objective-C(不带label,即直接从C++ 翻译来)// 方法原型// 方法名字是“insertObject::”// 这里的冒号:用来分隔参数,成为方法名的一部分(注意,这不同于 C++ 的域指示符::)-(void) insertObject:(id)anObject:(unsigned int)index// shelf 是 Array 类的一个实例,book 是一个对象[shelf insertObject:book:2];Objective-C(带有label)// 方法原型。

“index” 有一个标签“atIndex”// 方法名为“insertObject:atIndex:”// 这样的话,调用语句就很容易阅读了-(void) insertObject:(id)anObject atIndex:(unsigned int)index// shelf 是 Array 类的一个实例,book 是一个对象[shelf insertObject:book:2]; // 错误![shelf insertObject:book atIndex:2]; // 正确注意,方括号语法不应该读作“调用shelf 对象的insertObject 方法”,而应该是“向shelf 对象发送一个insertObject 消息”。

从 C++ 到 Objective-C 的快速指南

从 C++ 到 Objective-C 的快速指南

从 C++ 到 Objective-C 的快速指南当我开始为iOS写代码的时候,我意识到,作为一个C++开发者,我必须花费更多的时间来弄清楚Objective-C中怪异的东西。

这就是一个帮助C++专家的快速指南,能够使他们快速的掌握Apple的iOS语言。

请注意这绝不是一个完整的指南,但是它让你避免了阅读100页的手册。

除此之外,我知道你喜欢我的写作风格。

背景需要C++的技能,我会比较C++和Objective-C的东西。

此外,COM编程也是有用的,因为Objective-C有类似于IUnkown的东西,因此基础的COM编程是有帮助的(但不是必须的)Objective C++是C++和Objective C的组合。

你也能使用任何C++的东西混合到Objective C中,但是记住重新命名你的文件从.m到.mm铛 - 铛!我们马上就开始我们的教程. 首先我会介绍 Objective-C 的东西,然后是C++中与它对等的东西.成员函数1.// Objective-C2.- (int) foo : (int) a : (char) b {}3.+ (int) foo : (int) a : (char) b {}4.5.// C++6.int foo(int a,char b) {}7.static int foo(int a,char b) {}8.9.// Objective-C10.- (void) foo2 val1:(int) a; // named argument11.// <span id="22_nwp" style="width: auto; height: auto; float: none;"><a id="22_nwl" href="http://cpro.b /cpro/ui/uijs.php?adclass=0&app_id=0&c=news& cf=1001&ch=0&di=128&fv=18&is_app=0&jk=b2645dbfe197c8 8d&k=call&k0=call&kdi0=0&luki=1&n=10&p=baidu&q=06011 078_cpr&rb=0&rs=1&seller_id=1&sid=8dc897e1bf5d64b2&s sp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2 F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F4400%2Ehtml& urlid=0" target="_blank" mpid="22" style="text-decoration: none;"><span style="color:#0000ff;font-size:1 4px;width:auto;height:auto;float:none;">call</span>< /a></span>12.[obj foo2 val1:5]; // merely helper: You remember that 5 is assigned to param name val1.- 表示的是一个一般的成员函数(通过一个对象实体访问), 而 + 则表示一个静态成员函数, 不需要使用实体就能访问. 当然,像C++,静态成员不能访问实体变量.此外,Objective-C函数函数可以有赋予了名称的参数,这样让什么参数获得什么值会更一目了然. 理论上,被赋予了名称的参数允许程序员按任何顺序传入参数,但是Objective-C却规定要按声明的顺序传参.通过一个指针或者一个静态成员调用一个成员1.// Objective-C2.NSObject* ptr = ...; // some pointer3.[ptr foo:5:3]; // <span id="19_nwp" style="width: auto; height: auto; float: none;"><a id="19_nwl" href ="/cpro/ui/uijs.php?adclass=0&a pp_id=0&c=news&cf=1001&ch=0&di=128&fv=18&is_app=0&jk =b2645dbfe197c88d&k=call&k0=call&kdi0=0&luki=1&n=10& p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=8dc 897e1bf5d64b2&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922 429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument %2F4400%2Ehtml&urlid=0" target="_blank" mpid="19" st yle="text-decoration: none;"><span style="color:#000 0ff;font-size:14px;width:auto;height:auto;float:none ;">call</span></a></span> foo member with arguments5 and 34.[NSObject staticfoo:5:3]; // call static function of NSOBject with arguments 4 and 35.6.// C++7.CPPObject* ptr = ...; // some pointer8.ptr->foo(5,3);9.CPPObject::staticfoo(5,3);Objective-C 使用 [ ] 来调用成员函数并传入用:分割开的参数, 其对于ObjectiveC中ptr为nil的情况非常友好,在这种情况下“调用”将会被忽略掉(而在C++中,这种情况会抛出一个指针冲突异常 ). 这使得消除对nil对象的检查成为可能.协议VS接口1.// Objective-C2.@protocol foo3.- (void) somefunction;4.@end5.6.@interface c1 : NSObject<foo>7.8.@end9.10.@implementation c111.- (void) somefunction { ... }12.@end13.14.// C++15.class foo16.{17.virtual void somefunction() = 0;18.};19.20.class c1 : public NSObject, public foo21.{22.void somefunction() { ... }23.}协议= 抽象类. Objective-C 和 C++ 之间的区别在于,在 Objective-C 中, 函数并不是必须要被实现的. 你可以让一个可选的方法被动的被声明,而这仅仅只是向编译器发出暗示而已,并不是编译必须的.检查一个方法是否被实现了1./ Objective-C2.NSObject* ptr = ...; // some pointer3.[ptr somefunction:5:3]; // NSObject 不必一定为其编译而实现somefunction. 如果没有被实现的话,会引发异常.4.5.// C++6.CPPObject* ptr = ...; // some pointer7.ptr->somefunction(5,3); // CPPObject 必须实现 somefunction() 否则程序根本就不会被编译.Objective-C 成员函数就是(Smalltalk中的) "消息" 而在Objective-C中时,我们则说接收者 (即指针) 会向一个选择器做出回应, 这意味着其实现了我们尝试去调用的虚函数. 当有一个接口是, C++ 对象必须实现其所有的成员函数.而在 Objective-C 中这并不是必须的,因此我们可以向并不必须要实现它的某个地方发送一个”消息“ (如此就会引发一个异常).// Objective-CNSObject* ptr = ...; // some pointerif ([ptr respondsToSelector:@selector(somefunction::)][ptr somefunction:5:3];现在我们就可以确定接收者向选择器做出回应, 我们因此就可以调用它了. 在C++ 中不需要这样的检查, 因为实现必须常常”向选择器做出回应“, 否则源代码根本就不会被编译. 请注意我们必须知道选择器获取了多少个参数(因此在该@selector中是2个 ::s向下转型1.// Objective-C2.NSObject* ptr = ...; // some pointer3.if ([ptr isKindOfClass:[foo class]]4.[ptr somefunction:5:3];5.6.// C++7.CPPObject* ptr = ...; // some pointer8.foo* f = dynamic_cast<foo*>(ptr);9.if (f)10.f->somefunction(5,3);现在只有使用NSObject的"isKindOfClass"助手——所有Object-C类的基础,才能像在C++中那样向下转型.符合协议?1.// Objective-C2.NSObject* ptr = ...; // some pointer3.if ([ptr conformsToProtocol:@protocol(foo)]4.[ptr somefunction:5:3];5.6.// C++7.CPPObject* ptr = ...; // 某个也继承自foo的指针8.foo* f = ptr; // 或者<span id="15_nwp" style="width: auto; height: auto;float: none;"><a id="15_nwl" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=18&is_app=0&jk=b2645dbfe197c88d&k=%B1%E0%D2%EB%C6%F7&k0=%B1%E0%D2%EB%C6%F7&kdi0=0&luki=8&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=8dc897e1bf5d64b2&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F4400%2Ehtml&urlid=0" target="_blank" mpid="15" style="text-decoration: none;"><span style="color:#0000ff;font-size:14px;width:auto;height:auto;float:none;">编译器</span></a></span>会警告我们说ptr不能同foo兼容.9.f->somefunction(5,3);现在我们要检查接收器是否符合一个协议 (或者说,在C++就是实现一个接口), 以便我们可以发送这个协议包含的消息. 嘿嘿,它像极了Java的类和接口,而在C++中,完全被实现的类和一个“接口”之间没有技术上的差别.1.void* 、 id 或者 SEL?2.3.// Objective-C4.id ptr = ...; // some pointer5.if ([ptr conformsToProtocol:@protocol(foo)]6.[ptr somefunction:5:3];7.SEL s = @selector(foo:); // a pointer to a functionfoo that takes 1 parameter8.9.// C++10.void* ptr = ...; // some pointer11.foo* f = dynamic_cast<foo*>(ptr);12.if (f)13.f->somefunction(5,3);id 是通用的用于Objective-C类的类似于 void* 的东西. 你只能使用id而不是 void* 因为id可以通过ARC(稍后会详细介绍到它)编程一个可被管理的指针,而因此编译器需要在元指针类型和Objective-C指针之间做出区分. SEL 是一个用于选择器(C++函数指针)的通用类型,而你一般可以通过使用关键字@selector带上函数名字和:::::s的一个数字来创建一个选择器, 这取决于可以传入多少参数. 选择器实际上就是一个字符串,它会在运行时绑定到一个方法识别器.类定义,方法,数据,继承1.// Objective C2.@class f2; // forward declaration3.@interface f1 : NSOBject // Objective-C supports only public and single inheritance4.{5.int test; // default = protected6.@public7.int a;8.int b;9.f2* f;10.}11.- (void) foo;12.@end13.14.@implementation f115.- (void) foo16.{17.a = 5; // ok18.self->a = 5; // ok19.super.foo(); // parent <span id="11_nwp" style="width: auto; height: auto; float: none;"><a id="11_nwl"href="/cpro/ui/uijs.php?adclas s=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=18&is_app =0&jk=b2645dbfe197c88d&k=call&k0=call&kdi0=0&luki=1& n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&si d=8dc897e1bf5d64b2&ssp2=1&stid=0&t=tpclicked3_hc&tu= u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdoc ument%2F4400%2Ehtml&urlid=0" target="_blank" mpid="1 1" style="text-decoration: none;"><span style="color :#0000ff;font-size:14px;width:auto;height:auto;float :none;">call</span></a></span>20.}21.@end22.23.// C++24.class f1 : public CPPObject25.{26.int test; // default = private27.public:28.class f2* f; // forward declaration29.int a;30.int b;31.void foo();32.}33.34.void f1 :: foo()35.{36.a = 5; // ok37.this->a = 5; // ok38.CPPOBject::foo(); // parent call39.}Objective-C中的实现范围在@implementation/@end 标记 (在 C++ 中我们可以将实现放在任何带有::范围操作符的地方)之中. 它使用@class关键字用于事先声明. Objective-C 默认带有私有(private)保护, 但仅用于数据成员(方法必须是公共的). Objective-C 使用 self 而不是 this ,并且它还可以通过super关键字调用它的父类.构造器和析构器1.// Objective-C2.NSObject* s = [NSObject alloc] init]; // can returnnil if construction failed3.[s retain]; // Increment the ref count4.5.// C++6.CPPObject* ptr = new CPPObject(); // can throw7.ptr->AddRef();8.9.// Objective-C10.NSObject* s = [NSObject alloc] initwitharg:4];11.[s release];12.13.// C++14.CPPOBject* ptr = new CPPOBject(4);15.ptr->Release();Objective-C中的内存分配是通过静态成员方法alloc来实现的,所有 (做为NSObject后裔)的对象都有这个方法. self 在Objective-C中是可以被赋值的,而如果构建失败的话它就会设置成nil(而在C++中则会被抛出一个异常). 内存分配之后实际被构造器调用的是一个公共的成员函数,在Objective-C中默认的是init方法.Objective-C 使用同COM益阳的引用计数方法, 而它也使用 retain 和release (等同于IUnknown的 AddRef() 和 Release() 方法). 当引用计数到了0,则对象会从内存中被移除掉.多线程1.// Objective C2.@interface f1 : NSOBject // Objective-C supports only public and single inheritance3.{4.}5.- (void) foo;6.- (void) threadfunc :(NSInteger*) param;7.- (void) mt;8.9.@end10.11.@implementation f112.13.- (void) threadfunc : (NSInteger*) param14.{15.[self performSelectorOnMainThread: @selector(mt)];16.}17.18.- (void) mt19.{20.}21.22.- (void) foo23.{24.[self performSelectorInBackground: @selector(thradfunc:) withObject:1 waitUntilDone:false];25.<div></div>}26.@endObjective-C 有一些针对NSObject的内建功能,可以在另外一个线程中操作一个选择器 (== 调用一个成员), 在主线程中,等待一次调用等等 . 在NSObject 参见更多信息.内存和ARC1.// Objective-C2.@interface f1 : NSObject3.{4.}5.@property (weak) NSAnotherObject* f2; // 当没有其它强引用存在的时候,它将会被自动设置成@end-(void)foo{NSObject*s = [NSObject alloc]&nbsp;init]; // 如果构造失败的话会返回nil// use s// end. Hooraah! Compiler will automati<span id="9_nwp" style="width: auto; height: auto; float: none;"><a id="9_nwl" href="/cpro/ui/uijs.php?adclass=0&ap p_id=0&c=news&cf=1001&ch=0&di=128&fv=18&is_app=0&jk=b2645 dbfe197c88d&k=call&k0=call&kdi0=0&luki=1&n=10&p=baidu&q=0 6011078_cpr&rb=0&rs=1&seller_id=1&sid=8dc897e1bf5d64b2&ss p2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fww w%2Eadmin10000%2Ecom%2Fdocument%2F4400%2Ehtml&urlid=0" target="_blank" mpid="9" style="text-decoration:none;"><spanstyle="color:#0000ff;font-size:14px;width:auto;height:aut o;float:none;">call</span></a></span>y call[s release] for us!}这里需要你忘记自己良好的 C++ 习惯. OK Objective-C 使用了一个垃圾收集机制,这种东西我们C++很讨厌,因为它很慢并会让我们想到Java. 但是 ARC (自动进行引用计算) 是一种编译时间特性,它会告诉编译器 "这里是我的对象:请帮我算算啥时候它们才要被销毁吧". 使用ARC你就不需要发送retain/release 消息给你的对象了; 编译器会自动帮你代劳的.为了能帮助编译器决定保留一个对象多长时间,你还要一个弱引用指向一个变量. 默认的,所有的变量都是强引用(==只要强引用还存在,被引用的对象就会存在下去) . 你也可以获取一个弱引用,它会随着每个强引用消失而失去它的值. 这在类成员从XCode的Builder Interface(像RC 编辑器)处获取它们的值时,会很有用,当类被销毁时,那些成员也会失去它们的值.Strings1.// Objective-C2.NSString* s1 = @"hello";3.NSString* s2 = [NSString stringWithUTF8String:"A CString"];4.sprintf(buff,"%s hello to %@","there",s2);5.const char* s3 = [s2 UTF8String];NSString 是一个Objective-C字符串的不可变表示. 你可以使用其一个静态方法,或者是一个带有@前缀的字符串文本来创建NSString. 你也可以使用 %@ 来向printf家族函数来表示一个NSString,数组1.// Objective-C2.NSArray* a1 = [NSArray alloc] initWithObjects: @"hello",@"there",nil];3.NSString* first = [a1 objectAtIndex:0];NSArray和NSMutableArray是在Objective-C中处理数组的两个类(两者的差异是,NSArray元素构造时必须通过构造函数,而NSMutableArray可以在之后更改)。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

从C到O b j e c t i v e C类
和对象续
集团文件发布号:(9816-UATWW-MWUB-WUNN-INNUL-DQQTY-
从 C++ 到 Objective-C(4):类和对象(续)
作者:日期: 2011 年 03 月 19 日(9)
方法
Objective-C 中的方法与 C++ 的函数在语法方面风格迥异。

下面,我们就来讲述 Objective-C 的方法。

原型、调用、实例方法和类方法
以–开头的是实例方法(多数情况下都应该是实例方法);
以 + 开头的是类方法(相当于 C++ 里面的 static 函数)。

Objective-C 的方法都是 public 的;
返回值和参数的类型都需要用小括号括起来;
参数之间使用冒号:分隔;
参数可以与一个标签 label 关联起来,所谓标签,就是在 :
之前的一个名字。

标签被认为是方法名字的一部分。

这使得方法
比函数更易读。

事实上,我们应该始终使用标签。

注意,第一个
参数没有标签,通常它的标签就是指的方法名;
方法名可以与属性名相同,这使 getter 方法变得很简单。

C++
// 原型
void Array::insertObject(void*anObject, unsigned int atIndex); // shelf 是 Array 类的一个实例,book 是一个对象
shelf.insertObject(book, 2);
Objective-C(不带 label,即直接从 C++ 翻译来)
// 方法原型
// 方法名字是“insertObject::”
// 这里的冒号:用来分隔参数,成为方法名的一部分(注意,这不同于C++ 的域指示符::)
-(void) insertObject:(id)anObject:(unsigned int)index
// shelf 是 Array 类的一个实例,book 是一个对象
[shelf insertObject:book:2];
Objective-C(带有 label)
// 方法原型。

“index” 有一个标签“atIndex”
// 方法名为“insertObject:atIndex:”
// 这样的话,调用语句就很容易阅读了
-(void) insertObject:(id)anObject atIndex:(unsigned int)index // shelf 是 Array 类的一个实例,book 是一个对象
[shelf insertObject:book:2]; // 错误!
[shelf insertObject:book atIndex:2]; // 正确
注意,方括号语法不应该读作“调用 shelf 对象的 insertObject 方法”,而应该是“向 shelf 对象发送一个 insertObject 消息”。

这是Objective-C 的实现方式。

你可以向任何对象发送任何消息。

如果目标对象不能处理这个消息,它就会将消息忽略(这会引发一个异常,但不
会终止程序)。

如果接收到一个消息,目标对象能够处理,那么,目标对象就会调用相应的方法。

如果编译器能够知道目标对象没有匹配的方法,那么编译器就会发出一个警告。

鉴于 Objective-C 的前向机制,这并不会作为一个错误。

如果目标对象是 id 类型,那么在编译期就不会有警告,但是运行期可能会有潜在的错误。

this,self 和 super
一个消息有两个特殊的目标对象:self 和 super。

self 指当前对象(类似 C++ 的 this),super 指父对象。

Objective-C 里面没有 this 指针,取而代之的是 self。

注意,self 不是一个关键字。

实际上,它是每个消息接收时的隐藏参数,其值就是当前对象。

它的值可以被改变,这一点不同于 C++ 的
this 指针。

然而,这一点仅仅在构造函数中有用。

在方法中访问实例变量
同 C++ 一样,Objective-C 在方法中也可以访问当前对象的实例变量。

不同之处在于,C++ 需要使用 this->,而 Objective-C 使用的是
self->。

void f(void);
};
void Foo::f(void)
{
x =1;
int y;// 隐藏 this->y y =2;// 使用局部变量y
this->y =3;// 显式使用成员变量
}}
-(void) f;
@end
@implementation Foo
-(void) f
{
x =1;
int y; // 隐藏 this->y y =2; // 使用局部变量y
self->y =3; // 显式使用成员变量
}
@end
原型的 id、签名和重载
函数就是一段能够被引用的代码,例如使用函数指针。

一般的,方法名会作为引用方法的唯一 id,但是,这就需要小心有重载的情况。

C++ 和Objective-C 使用截然不同的两种方式去区分:前者使用参数类型,后者使用参数标签。

在 C++ 中,只要函数具有不同的参数类型,它们就可以具有相同的名字。

const 也可以作为一种重载依据。

C++
int f(int);
int f(float);// 允许,float 和 int 是不同类型
class Foo
{
public:
int g(int);
int g(float);// 允许,float 和 int 是不同类型
int g(float)const;// 允许,const 可以作为重载依据
};
class Bar
{
public:
int g(int);// 允许,我们使用的是 Bar::,而不是 Foo::
}
在 Objective-C 中,所有的函数都是普通的 C 函数,不能被重载(除非指定使用 C99 标准)。

方法则具有不同的语法,重载的依据是label。

Objective-C
int f(int);
int f(float); // 错误!C 函数不允许重载
@interface Foo :NSObject
{
}
-(int) g:(int) x;
-(int) g:(float) x; // 错误!类型不同不作为重载依据,同上一个没有区别
-(int) g:(int) x :(int) y; // 正确:两个匿名 label
-(int) g:(int) x :(float) y; // 错误:同上一个没有区别
-(int) g:(int) x andY:(int) y; // 正确:第二个 label 是“andY”
-(int) g:(int) x andY:(float) y; // 错误:同上一个没有区别
-(int) g:(int) x andAlsoY:(int) y; // 正确:第二个 label 是“andAlsoY”
@end
基于 label 的重载可以很明白地解释方法的名字,例如:
@interface Foo :NSObject{}
// 方法名是“g”
-(int) g;
// 方法名是“g:”
-(int) g:(float) x;
// 方法名是“g::”
-(int) g:(float) x :(float) y;
// 方法名是“g:andY:”
-(int) g:(float) x andY:(float) y;
// 方法名是“g:andZ:”
-(int) g:(float) x andZ:(float) z;
@end
显然,Objective-C 的方法使用 label 区分,而不是类型。

利用这种机制,我们就可以使用选择器 selector 来指定一个方法,而不是“成员函数指针”。

相关文档
最新文档