ios面试

 1.Objective-C中,与alloc语义相反的方法是dealloc还是release?与retain语义相反的方法是dealloc还是release,为什么?需要与alloc配对使用的方法是dealloc还是release,为什么?

答:alloc与dealloc语意相反,alloc是创建变量,dealloc是释放变量。 retain 对应release,retain 保留一个对象。调用之后,变量的计数加1

 

2.什么是retain count?

  答:引用计数(ref count或者retain count)。对象的内部保存一个数字,表示被引用的次数。例如,某个对象被两个指针所指向(引用)那么它的retain count为2。需要销毁对 象的时候,不直接调用dealloc,而是调用release。release会让retain count减1,只有retain count等于0,系统才会调用dealloc真正销毁这个对象。

 

3.以下每行代码执行后,person对象的retain count分别是多少

1.    Person *person = [[Person alloc] init]; count 1   

2.    [person retain]; count 2   

3.    [person release];count 1   

4.    [person release];count = 0;  

 

4.什么时候用delegate,什么时候用Notification?

  答:delegate针对one-to-one关系,并且reciever可以返回值给sender,notification 可以针对one-to-one/many/none,reciever无法返回值给sender.所以,delegate用于sender希望接受到reciever的某个功能反馈值,notification用于通知多个object某个事件。

 

5.什么是KVC和KVO?

  答:KVC(Key-Value-Coding)内部的实现:一个对象在调用setValue的时候,(1)首先根据方法名找到运行方法的时候所需要的环境参数。(2)他会从自己isa指针结合环境参数,找到具体的方法实现的接口。(3)再直接查找得来的具体的方法实现。KVO(Key-Value-Observing):当观察者为一个对象的属性进行了注册,被观察对象的isa指针被修改的时候,isa指针就会指向一个中间类,而不是真实的类。所以isa指针其实不需要指向实例对象真实的类。所以我们的程序最好不要依赖于isa指针。在调用类的方法的时候,最好要明确对象实例的类名。

 

6.ViewController 的 didReceiveMemoryWarning 是在什么时候被调用的?默认的操作是什么?

答:默认调用[super didReceiveMemoryWarning] 

当内错过低的时候会调用次方法

 

7.执行下面代码有什么问题会不会造成内存泄露为什么?

for(intindex = 0; index < 20; index ++){
NSString *tempStr = @
”tempStr”;
NSLog(tempStr);
NSNumber *tempNumber = [NSNumber numberWithInt:2];
NSLog(tempNumber);
}

答:NSLog(tempNumber);应该写成NSLog(@"%@",tempNumber);
直接打印一个 NSNumber应该不会调用 他的description会出类型错误

会不会造成内存泄露得看多线程自己的实现.这里的2个类.如果thread里没在开头和结尾加一个autoreleasepool 会泄露.

大循环时自动释放池写内好还时外好.得看具体情况.循环内步骤多不多.否则 创建 自动释放池 释放也时额外开销.得不偿失.不如.用[alloc init]然后循环尾部手动release
否则循环内较好

 

8.#import跟#include 又什么区别 #import<> 跟 #import""又什么区别?
答:#import 比起#include 保证#import 的头文件 只会被引用一次.#import<>的文件 在实际运用中都是某个框架里的.#import <Three20/Three20.h><>通常指向的是一个目录#import ""则直接是文件名

 

9、Object-C有私有方法吗?私有变量呢?

objective-c – 类里面的方法只有两种, 静态方法和实例方法. 这似乎就不是完整的面向对象了,按照OO的原则就是一个对象只暴露有用的东西. 如果没有了私有方法的话, 对于一些小范围的代码重用就不那么顺手了. 在类里面声名一个私有方法

@private可以用来修饰私有变量

在Objective‐C中,所有实例变量默认都是私有的,所有实例方法默认都是公有的

 

10.main()

int a[5]={1,2,3,4,5}; 
int *ptr=(int *)(&a+1); 
printf(“%d,%d”,*(a+1),*(ptr-1)); 
}

答:2,5
*
(a+1)就是a[1],*(ptr-1)就是a[4],执行结果是2,5
&a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int)
int *ptr=(int *)(&a+1);
则ptr实际是&(a[5]),也就是a+5

原因如下:
&a
是数组指针,其类型为 int (*)[5];
而指针加1要根据指针类型加上一定的值,不同类型的指针+1之后增加的大小不同。
a是长度为5的int数组指针,所以要加 5*sizeof(int)
所以ptr实际是a[5]
但是prt与(&a+1)类型是不一样的(这点很重要)
所以prt-1只会减去sizeof(int*)
a,&a的地址是一样的,但意思不一样
a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址,
a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5].

 

11.以下为Windows NT下的32位C++程序,请计算sizeof的值

voidFunc ( char str[100] )
{
sizeof( str ) = ?
}
void *p = malloc( 100 );
sizeof ( p ) = ?

这 题很常见了,Func ( char str[100] )函数中数组名作为函数形参时,在函数体内,数组名失去了本身的内涵,仅仅只是一个指针;在失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。Windows NT 32位平台下,指针的长度(占用内存的大小)为4字节,故sizeof( str ) 、sizeof( p ) 都为4。

 

12.用预处理指令#define声明一个常数,用以表明1年中有多少秒(忽略闰年问题)
#define SECONDS_PER_YEAR (60 * 60 * 24 *365)UL
我在这想看到几件事情:
•; #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等)
•; 懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。

•;意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。
•; 如果你在你的表达式中用到UL(表示无符号长整型),那么你有了一个好的起点。记住,第一印象很重要。

写一个“标准“宏MIN 
,这个宏输入两个参数并返回较小的一个。

#defineMIN(A,B)
((A)<= (B) ? (A) : (B))
这个测试是为下面的目的而设的:
•;
标识#define在宏中应用的基本知识。这是很重要的,因为直到嵌入(inline)操作符变为标准C的一部分,宏是方便产生嵌入代码的唯一方
法,对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。

•;三重条件操作符的知识。这个操作符存在C语言中的原因是它使得编译器能产生比 if-then-else
更优化的代码,了解这个用法是很重要的。

•;懂得在宏中小心地把参数用括号括起来
•;
我也用这个问题开始讨论宏的副作用,例如:当你写下面的代码时会发生什么事?
least = MIN(*p++, b);

结果是:
((*p++) <= (b) ? (*p++) : (*p++))
这个表达式会产生副作用,指针p会作三次++自增操作。

 

13.写一个委托的interface

@protocolMyDelegate;

@interfaceMyClass: NSObject
{
id <MyDelegate> delegate;
}

// 委托方法
@protocol MyDelegate
- (void)didJobs:(NSArray *)args;
@end


14
.写一个NSString类的实现
+ (id)initWithCString:(c*****t char*)nullTerminatedCString encoding:(NSStringEncoding)encoding;
+ (id) stringWithCString: (c*****t char*)nullTerminatedCString
encoding: (NSStringEncoding)encoding
{
NSString *obj;
obj = [self allocWithZone: NSDefaultMallocZone()];
obj = [obj initWithCString: nullTerminatedCString encoding: encoding];
return AUTORELEASE(obj);
}

 

15.关键字const有什么含意?修饰类呢?static的作用?用于类呢?还有extern C的作用

·   const意味着只读

       const int a;  a为一个常整型数

       int const a;  同上,a为一个常整型数

       const int *a; a为指向常整型数的指针(即整型数不可修改,但是指针可以)

       int* const a; a为指向整型数的常指针(即整型数可以修改,但是指针不可修改)

       int const *aconst; a为一个指向常整数的常指针

static关键字作用

(1)函数体内 static 变量的作用范围为该函数体,不同于 auto 变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;

(2)在模块内的 static 全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;

(3)在模块内的 static 函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;

(4)在类中的 static 成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;

(5)在类中的 static 成员函数属于整个类所拥有,这个函数不接收 this 指针,因而只能访问类的static 成员变量。 

extern "C"的作用

(1)被 extern"C"限定的函数或变量是 extern 类型的;

 extern 是 C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器, 
其声明的函数和变量可以在本模块或其它模块中使用。

(2)被 extern"C"修饰的变量和函数是按照 C 语言方式编译和连接的;

extern "C"的惯用法  

(1)在 C++中引用 C 语言中的函数和变量,在包含 C 语言头文件(假设为 cExample.h)时,需进 
行下列处理: 
extern "C"  
{  
#include "cExample.h"  
}  
而在 C 语言的头文件中,对其外部函数只能指定为 extern类型,C 语言中不支持 extern"C"声明, 
在.c 文件中包含了 extern "C"时会出现编译语法错误。 

(2)在 C 中引用 C++语言中的函数和变量时,C++的头文件需添加 extern "C",但是在 C 语言中不 
能直接引用声明了 extern "C"的该头文件,应该仅将 C 文件中将 C++中定义的extern "C"函数声明为 
extern 类型。

 

16.为什么标准头文件都有类似以下的结构? 
#ifndef __INCvxWorksh
#define __INCvxWorksh
#ifdef __cplusplus
extern
“C” {
#endif
/*…*/
#ifdef __cplusplus
}
#endif
#endif /* __INCvxWorksh */
显然,头文件中的编译宏“#ifndef __INCvxWorksh、#define __INCvxWorksh、#endif” 的作用
是防止该头文件被重复引用。

11.#import跟#include的区别,@class呢?

@class一般用于头文件中需要声明该类的某个实例变量的时候用到,在m文件中还是需要使用#import
而#import比起#include的好处就是不会引起交叉编译

17.obj-c的优缺点
objc
优点:
1) Cateogies
2) Posing
3)
动态识别
4)
指标计算
5
)弹性讯息传递
6)
不是一个过度复杂的 C 衍生语言
7) Objective-C
C++ 可混合编程
缺点:
1)
不支援命名空间
2)
不支持运算符重载
3
不支持多重继承
4
使用动态运行时类型,所有的方法都是函数调用,所以很多编译时优化方法都用不到。(如内联函数等),性能低劣。

 

18.readwrite,readonly,assign,retain,copy,nonatomic属性的作用
@property是一个属性访问声明,扩号内支持以下几个属性:

1
getter=getterNamesetter=setterName,设置settergetter的方法名
2
readwrite,readonly,设置可供访问级别
2
assignsetter方法直接赋值,不进行任何retain操作,为了解决原类型与环循引用问题
3
retainsetter方法对参数进行release旧值再retain新值,所有实现都是这个顺序(CC上有相关资料)
4
copysetter方法进行Copy操作,与retain处理流程一样,先旧值release,再Copy出新的对象,retainCount1。这是为了减少对上下文的依赖而引入的机制。
5
nonatomic,非原子性访问,不加同步,多线程并发访问会提高性能。注意,如果不加此属性,则默认是两个访问方法都为原子型事务访问。锁被加到所属对象实例级(我是这么理解的…)

 

19..自动释放池是什么,如何工作

您向一个对象发送一个autorelease消息时,Cocoa就会将该对象的一个引用放入到最新的自动释放池。它仍然是个正当的对象,因此自动释放池定义的作用域内的其它对象可以向它发送消息。当程序执行到作用域结束的位置时,自动释放池就会被释放,池中的所有对象也就被释放。
1. ojc-c
通过一种”referring counting”(引用计数)的方式来管理内存的, 对象在开始分配内存(alloc)的时候引用计数为一,以后每当碰到有copy,retain的时候引用计数都会加一, 每当碰到releaseautorelease的时候引用计数就会减一,如果此对象的计数变为了0, 就会被系统销毁.
2. NSAutoreleasePool
就是用来做引用计数的管理工作的,这个东西一般不用你管的.
3. autorelease
release没什么区别,只是引用计数减一的时机不同而已,autorelease会在对象的使用真正结束的时候才做引用计数减一.

20..c和obj-c如何混用
1
obj-c的编译器处理后缀为m的文件时,可以识别obj-cc的代码,处理mm文件可以识别obj-c,c,c++代码,但cpp文件必须只能用c/c++代码,而且cpp文件include的头文件中,也不能出现obj-c的代码,因为cpp只是cpp
2)
mm文件中混用cpp直接使用即可,所以obj-ccpp不是问题
3
)在cpp中混用obj-c其实就是使用obj-c编写的模块是我们想要的。
如果模块以类实现,那么要按照cpp class的标准写类的定义,头文件中不能出现obj-c的东西,包括#import cocoa的。实现文件中,即类的实现代码中可以使用obj-c的东西,可以import,只是后缀是mm
如果模块以函数实现,那么头文件要按c的格式声明函数,实现文件中,c++函数内部可以用obj-c,但后缀还是mmm

结:只要cpp文件和cpp include的文件中不包含obj-c的东西就可以用了,cpp混用obj-c的关键是使用接口,而不能直接使用实现代码,实际上cpp混用的是 obj-c编译后的o文件,这个东西其实是无差别的,所以可以用。obj-c的编译器支持cpp.

21..堆和栈的区别

管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak
申请大小:
栈:Windows,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在 WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。
碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出
分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。
分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的。

22.列举几种进程的同步机制,并比较其优缺点。
答案:原子操作信号量机制自旋锁管程,会合,分布式系统
进程之间通信的途径
答案:共享存储系统消息传递系统管道:以文件系统为基础
进程死锁的原因
答案:资源竞争及进程推进顺序非法
死锁的4个必要条件
答案:互斥、请求保持、不可剥夺、环路
死锁的处理
答案:鸵鸟策略、预防策略、避免策略、检测与解除死锁

 

23.IOS操作系统的层次结构

1Core OS 核心层:包含Accelerate FrameworkExternal Accessory FrameworkSecurity FrameworkSystem等几个框架,基本都是基于c语言的接口

2Core Services核心服务层:包含Address Book FrameworkCFNetwork FrameworkCore Data FrameworkCore Foundation FrameworkCore Location FrameworkCore Media FrameworkCore Telephony FrameworkEvent Kit FrameworkFoundation FrameworkMobile Core Services FrameworkQuick Look FrameworkStore Kit FrameworkSystem Configuration FrameworkBlock ObjectsGrand Central Dispatch  In App PurchaseLocation ServicesSQLiteXML Support等一些框架,也基本都是基于c语言的接口。

3Mediah媒体层:包含Core GraphicsCore AnimationOpenGL ESCore TextImage I/OAssets Library FrameworkMedia Player FrameworkAV FoundationOpenALCore Audio FrameworksCore Media等等

4 Cocoa Touch 触摸层:包括Address Book UI FrameworkEvent Kit UI FrameworkGame Kit FrameworkiAd FrameworkMap Kit FrameworkMessage UI FrameworkUIKit Framework等等,这一层基本都是基于 Objective-c的接口

24.Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么?
如果说多重继承指的是.2个类继承属性和方法.答案是不行.
可以实现多个接口么?可以.Category (分类)可以拓展这个类.添加额外的方法.
Category
(分类)使得在不修改该类原先代码的情况下.拓展或者修改现有类的定义.并且是向下有效的.既会影响到该类所有子类.

重写一个类的方式用继承还是分类.取决于具体情况.假如目标类有许多的子类.我们需要拓展这个类又不希望影响到原有的代码.继承后比较好.
如果仅仅是拓展方法.分类更好.(不需要涉及到原先的代码)

 

25.id声明的对象有什么特性?
id
类型是通用指针类型:因为通过指针,也就是内存地址来引用对象,所以可以自由地将它们在id变量之间来回赋值。因此返回id类型值的方法只是返回指向内存中某对象的指针。然后可以将该值赋给任何对象变量。因为无论在哪里,对象总是携带它的isa成员,所以即使将它存储在id类型的通用对象变量中,也总是可以确定它的类。

 

26..写一个NSString类的实现

+idinitWithCSting:(const char *)nullTerminatedCStringencoding:(NSStringEncoding)encoding;

+(id)stringWithCString:(const char *)nullTerminatedCStringencoding:(NSStringEncoding)encoding;

{

}

 

常见的object-c的数据类型有那些,C的基本数据类型有什么区别?如:NSIntegerint

: object-c的数据类型有NSStringNSNumberNSArrayNSMutableArrayNSData等等,这些都是class,创建后便是对象,而C语言的基本数据类型int,只是一定字节的内存空间,用于存放数值;而object-cNSNumber包含有父类NSObject的方法和 NSNumber自己的方法,可以完成复杂的操作。

 

27.ObjectC中创建线程的方法是什么?如果在主线程中执行代码,方法是什么?如果想延时执行代码、方法又是什么?

答案:线程创建有三种方法:使用NSThread创建、使用 GCDdispatch、使用子类化的NSOperation,然后将其加入NSOperationQueue;在主线程执行代码,方法是 performSelectorOnMainThread,如果想延时执行代码可以用performSelector:onThread:withObject:waitUntilDone:

 

28..在一个对象的方法里面:

self.name = object;

name =”object

  有什么不同吗

  答:self.name ="object"会调用对象的setName()方法,name = "object"会直接把object赋值给当前对象的name 属性。

[backcolor=transparent][backcolor=transparent]

 

29.为什么很多内置类如UITableViewController的delegate属性都是assign而不是retain的?

  答:会引起循环引用。

31.30.XML有哪些解析技术?区别是什么?  

:DOM,SAX,STAXDOM:处理大型文件时其性能下降的非常厉害。这个问题是由DOM的树结构所造成的,这种结构占用的内存较多,而且DOM必须在解析文件之前把整个文档装入内存,适合对XML的随机访问;SAX:不现于DOM,SAX是事件驱动型的XML解析方式。它顺序读取XML文件,不需要一次全部装载整个文件。当遇到像文件开头,文档结束,或者标签开头与标签结束时,它会触发一个事件,用户通过在其回调事件中写入处代码来处理XML文件,适合对XML的顺序访问;STAX:Streaming APIfor XML (StAX)

32.html中post和get区别,是不是用get的方法用post都能办到?

1. get是从服务器上获取数据,post是向服务器传送数据。 2. get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到。post是通过HTTP post机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址。用户看不到这个过程。 3. 对于get方式,服务器端用Request.QueryString获取变量的值,对于post方式,服务器端用Request.Form获取提交的数据。 4. get传送的数据量较小,不能大于2KBpost传送的数据量较大,一般被默认为不受限制。但理论上,IIS4中最大量为80KBIIS5中为100KB 5. get安全性非常低,post安全性较高。但是执行效率却比Post方法好。建议: 1get方式的安全性较Post方式要差些,包含机密信息的话,建议用Post数据提交方式; 2、在做数据查询时,建议用Get方式;而在做数据添加、修改或删除时,建议用Post方式;

 

33.类工厂方法是什么 

类工厂方法的实现是为了向客户提供方便,它们将分配和初始化合在一个步骤中,返回被创建的对象,并进行自动释放处理。这些方法的形式是+ (type)className...(其中 className不包括任何前缀)。工厂方法可能不仅仅为了方便使用。它们不但可以将分配和初始化合在一起,还可以为初始化过程提供对 象的分配信息。 类工厂方法的另一个目的是使类(比如NSWorkspace)提供单件实例。虽然init...方法可以确认一 个类在每次程序运行过程只存在一个实例,但它需要首先分配一个生的实例,然后还必须释放该实例。 工厂方法则可以避免为可能没有用的对象盲目分配内存。 

 

34.单件实例是什么 

Foundation  Application Kit 框架中的一些类只允许创建单件对象,即这些类在当前进程中的唯一实例。举例来说,NSFileManager NSWorkspace 类在使用时都是基于进程进行单件对象的实例化。当向这些类请求实例的时候,它们会向您传递单一实例的一个引用,如果该实例还不存在,则首先进行实例的分配和初始化。单件对象充当控制中心的角色,负责指引或协调类的各种服务。如果类在概念上只有一个实例(比如 NSWorkspace),就应该产生一个单件实例,而不是多个实例;如果将来某一天可能有多个实例,您可 以使用单件实例机制,而不是工厂方法或函数。

35.ViewController loadViewviewDidLoadviewDidUnload分别是什么时候调用的,在自定义ViewCointroller时在这几个函数中应该做什么工作?

init方法
init方法中实例化必要的对象(遵从LazyLoad思想)‍init方法中初始化ViewController本身
 loadView
方法
view需要被展示而它却是nil时,viewController会调用该方法。不要直接调用该方法。
如果手工维护views,必须重载重写该方法如果使用IB维护views,必须不能重载重写该方法loadViewIB构建view你在控制器中实现了loadView方法,那么你可能会在应用运行的某个时候被内存管理控制调用。如果设备内存不足的时候, view 控制器会收到didReceiveMemoryWarning的消息。默认的实现是检查当前控制器的view是否在使用。如果它的view不在当前正在使用的view hierarchy里面,且你的控制器实现了loadView方法,那么这个view将被release, loadView方法将被再次调用来创建一个新的view

loadView指不使用xib,用代码实现控件。

viewDidLoad方法
viewDidLoad
此方法只有当viewnib文件初始化的时候才被调用。
重载重写该方法以进一步定制viewiPhone OS 3.0及之后的版本中,还应该重载重写viewDidUnload来释放对view的任何索引viewDidLoad后调用数据Model
viewDidUnload
方法‍
当系统内存吃紧的时候会调用该方法(注:viewController没有被dealloc
内存吃紧时,在iPhone OS 3.0之前didReceiveMemoryWarning是释放无用内存的唯一方式,但是OS 3.0及以后viewDidUnload方法是更好的方式在该方法中将所有IBOutlet(无论是property还是实例变量)置为nil(系统release view时已经将其release掉了)
在该方法中释放其他与view有关的对象、其他在运行时创建(但非系统必须)的对象、在viewDidLoad中被创建的对象、缓存数据等 release对象后,将对象置为nilIBOutlet只需要将其置为nil,系统release view时已经将其release掉了)一般认为viewDidUnloadviewDidLoad的镜像,因为当view被重新请求时,viewDidLoad还会重新被执行
viewDidUnload
中被release的对象必须是很容易被重新创建的对象(比如在viewDidLoad或其他方法中创建的对象),不要release用户数据或其他很难被重新创建的对象
dealloc
方法viewDidUnloaddealloc方法没有关联,dealloc还是继续做它该做的事情。

 

36.面向对象的三个基本特征是:封装、继承、多态。

 

封装

封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。

封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。

继承

面向对象编程 (OOP) 语言的一个主要功能就是继承。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。

通过继承创建的新类称为“子类”或“派生类”。

被继承的类称为基类父类超类

继承的过程,就是从一般到特殊的过程。

要实现继承,可以通过继承Inheritance)和组合Composition)来实现。

在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。

 

继承概念的实现方式有三类:实现继承、接口继承和可视继承。

Ø         实现继承是指使用基类的属性和方法而无需额外编码的能力;

Ø         接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力;

Ø         可视继承是指子窗体(类)使用基窗体(类)的外观和实现代码的能力。

在考虑使用继承时,有一点需要注意,那就是两个类之间的关系应该是属于关系。例如,Employee 是一个人,Manager 也是一个人,因此这两个类都可以继承 Person 类。但是 Leg类却不能继承 Person 类,因为腿并不是一个人。

抽象类仅定义将由子类创建的一般属性和方法,创建抽象类时,请使用关键字 Interface 而不是 Class

OO开发范式大致为:划分对象抽象类将类组织成为层次化结构(继承和合成) →用类与实例进行设计和实现几个阶段。

 

多态

多态性(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。

实现多态,有二种方式,覆盖,重载。

覆盖,是指子类重新定义父类的虚函数的做法。

重载,是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。

其实,重载的概念并不属于面向对象编程,重载的实现是:编译器根据函数不同的参数表,对同名函数的名称做修饰,然后这些同名函数就成了不同的函数(至少对于编译器来说是这样的)。如,有两个同名函数:function func(p:integer):integer;function func(p:string):integer;。那么编译器做过修饰后的函数名称可能是这样的:int_funcstr_func。对于这两个函数的调用,在编译器间就已经确定了,是静态的(记住:是静态)。也就是说,它们的地址在编译期就绑定了(早绑定),因此,重载和多态无关!真正和多态相关的是覆盖。当子类重新定义了父类的虚函数后,父类指针根据赋给它的不同的子类指针,动态(记住:是动态!)的调用属于子类的该函数,这样的函数调用在编译期间是无法确定的(调用的子类的虚函数的地址无法给出)。因此,这样的函数地址是在运行期绑定的(晚邦定)。结论就是:重载只是一种语言特性,与多态无关,与面向对象也无关!引用一句Bruce Eckel的话:不要犯傻,如果它不是晚邦定,它就不是多态。

那么,多态的作用是什么呢?我们知道,封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用家谱中任一类的实例的某一属性时的正确调用。

37.这段代码有什么问题,如何修改
for (int i = 0; i < someLargeNumber; i++)
{
NSString *string = @”Abc”;
string = [string lowercaseString];
string = [string stringByAppendingString:@"xyz"];
NSLog(@“%@”, string);
}
答:会内存泄露,加一个自动释放池

 for(int i = 0; i<1000;i++){
NSAutoreleasePool * pool1 = [[NSAutoreleasePool alloc] init];
NSString *string = @”Abc”;
string = [string lowercaseString];
string = [string stringByAppendingString:@"xyz"];
NSLog(@”%@”,string);
[pool1 drain];
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值