答:没有!这个是确定的。(委托只能代替继承!)类别。在类的一个类别里面添加方法,而所添加的方法会被原来的类所拥有,这至关于多继承。可是类别有一个重要的限制,致使它很鸡肋,不能添加实便变量。固然这个是有解决办法的,好比存取方法,能够在其中来存取静态全局变量,或者使用运行时api动态添加实例变量。第二个方法是使用消息转发。ios
关于多继承,我还有一些要说。多继承的做用是什么?多继承能够为一个类添加额外的方法,抽象来讲的话能够为一个类添加额外的行为而可能影响,又或者不影响原来的行为。那么多继承的应用状况就这两种了,一是一个类已经定义好了,它已经有了它本身的父类,这时你须要为经添加一些新的方法,新的行为,这就须要多继承的。在这种状况下,多继承的做用说白了,就是添加方法,那么类别是彻底能够知足须要的,若是不须要添加实例变量的话,固然还有一种方法,那就是动态添加方法。 可是还有一种状况,多个类已经定义好了,而他们又有各自的父类,而这时你须要为他们添加共同,或者相似的方法,好比你不想一份代码写屡次,减小冗余,这时你能够定义一个新的基类,实现这个须要共有的方法而由这几个类共同继承,这时,多继承的意义即是共用。这时,类别就彻底不够用了。这时,应该使用委托,注意,这里的委拖不一样于delegate模式,而是一种广义上的委托,好比这几个类要作一件共同的事,那么就新定义一个类,用来实现这个任务,而原来的这几个类则将任务委托给它来作。c++
不管你的变量放在哪里,只要我想,总能拿的到,kvc就是用来干这个的!可是放在.m文件,类扩展里的方法和变量,实际上对于别的类来讲是不可见的,能够理解为私有的属性。程序员
static的主要做用是隐藏。对于变量来讲,不加static的全局变量是全局可见的,在其余的文件中也能够被访问到。而加了static的全局变量却只能在本文件被访问。而局部变量若是加了static修饰,则会被放到静态存储区,在局部函数被再次访问的时候他的值仍是会保持前一次的状态,另外,这个变量只会被初始化一次,并且应该只能用直接量来进行初始化,在程序第一次遇到它的时候进行初始化,换言之,它不能被动态的值初始化。举例来讲,static a = 1;可是static a = b就不行。函数也是起到全局的隐藏效果。对于c++来讲,static能够用来定义静态方法。
因此静态全局变量相对于普通全局变量来讲的好处就是不会被其余文件所使用,和避免命名冲突。
局部函数中所声明变量叫自动变量,它们会被放在栈中,随着函数的退出,这些空间会被释放。而由程序动态分配的变量则是放在堆中。全局变量放在静态数据区中。面试
下面是c++中的static所起的做用。api
在成员前加static修饰能够成为类静态员,类全部,为全部该类的对象共享。静态方法具备相同的特性。数组
即便屡次@import一个文件,该文件也只会被引用一次 #include则不一样。@class告诉类声明,这个类在实现的时候才去查找他的定义,这个标识能够用来防止交叉编译。安全
进程能够理解为程序的一次执行,而线程则是进程中的一个片断。并发
1)进程间是独立的,通常而言进程是没法突破程序的边界限制而去访问另外一个进程的存储空间,而一个进程的线程则共享这个进程的存储空间,并能够进行互相通讯。 2)通常而言,进程至少须要一个线程,但能够多于一个,但线程却只属于一个进程,而且只能属于一个。 3)其实线程就是一个简化版的进程,它的划分尺度小进程,从而使系统的并发程度提升。 4)进程是程序的一次运行,是系统进行资源分配和调度的一个独立单位。线程是cpu调度和分派的基本单位。 5)一个线程能够建立和撤消另外一个线程;同一个进程之中的多个线程能够并发执行。
六、关于内存管理:ios的内存管理使用的是引用计数模式。所谓引用计数模式,是相对于垃圾回收机制来讲的。对于有垃圾回收机制的语言,程序中所建立的内存会被系统所管理,在必定的时候进行回收,程序员只管建立而不须要去释放。相对的,使用引用计数模式的语言中,程序员须要对程序中所申请的内存负责。每个对象都维护着一个引用计数值,当一个新的引用指向它时,引用计数器就递增,去掉一个引用时,计数器就递减,当计数器的值为0时,系统便认为它是无人须要的,这时即可去它所占有的资源进行回收。函数
具体到ios里面来讲,当一个对象被建立时,它的引用计数为1,具体到ios语句,为alloc。一个被建立的对象能够被继续引用,这时使用的是retain,它告诉这个对象,我要使用你了,在我结束使用你之前,请不要死。而这时该对象则对它做出回应,而且自身的引用计数加1。当对象结束使用它时,对它发送release消息,告诉它我不使用你了,相应的该对象则将本身的引用计数减一。直到没有引用直向这个对象的时候,也就是说这个对象的引用计数为0了,系统认为这个对象已经没有用了,将会对它进行回收。 注意,以上所内容所说的引用为强引用。还有一种引用叫弱引用。简单来讲,对一个对象的弱引用,代表我知道你在那里,我会用你,可是你是死是活与我无关。即,弱引用持有一个对象的指针,但没有属于它的引用计数。 以上所陈述的是ios内存管理的一些基本的原理。实际操做上没有这么复杂,只要明白几条基本的规则就能保证内存的合理应用。一是谁建立谁释计,谁(强)引用谁释放,这样就保证了强引用与引用释放的一一对应,避免了只引用不释放和过分释放问题的发生。二是对于强引用的对象能够发送自动释放,也就是autorelease来进行释放;收到autorelease消息的对象会在未来的某一刻本身将引用计数减一。三是做为返回值的强引用对象要发送autorelease消息,好比你在一个方法里面局部建立了一个对象,而且要将这个对象做为该方法的返回值返回,那么在这以前你须要对它发送autorelease消息。四是对于retain的属性,要在deleac函数里面对它进行释放并置空。也可使用self.property = nil这样的语句,这个语句与arc方法进行了统一。五是使用弱引用避免引用回环。引用回环多出如今代理模式上,实际项目中咱们常看到a.delegate = self的语句,实际上这里a的property属性可能是弱引用以免引用回环。 虽然上文频频提到强引用与弱引用,而且指出,所谓强引用是指持有指针加引用计数加1,可是这两项因素并无特定的联系。在这种状况下,实际内存是不安全的,由于一个弱引用也能够对该对象发送release消息,而被引用对象并不知道对它发送release消息的对象是否持有一个有效的引用计数;同时一个强引用也能够在不对它发送release消息的状况下将这个引用抛掉,而该对象仍会去等待这个引用所持有的引用计数减1。因此,在非arc状况下的强弱引用只是一个概念上的东西。举个例子来讲,若是a对b进行了retain,而且a且持有了b的指针,这时咱们能够说a对b持有强引用。但实际上a能够将这个指针抛掉而并不对b发送release消息,这时没有一个有用的指针指向b,而b并不知道a已经抛弃了它,仍会一直等待,这时便出现了咱们常说的内存泄漏。另外一种状况是,出现了另外一外对象c,它对b持有指针但并无属于它的引用,而他仍能够向b发送release消息,b并不知道是a仍是别的谁发送了release消息,但它仍会对这个release消息作出响应并将引用计数减一。这时b实际的引用计数值已经为0,而且被释放,而当a最终找到b并对b发送release消息的时候,它所持有的实际是一个已经被系统回收了的对象,这时便发生了咱们常说的过分释放。 在非arc状况下,强引用与弱引用的维护全在程序员的身上。 另外说一下arc。对于arc首先要强调一点,arc并非垃圾回收,虽然它简化了内存管理,但它实际上仍是引用计数,只不过从手动变成了自动,更确切一点说,它实际上是将在非arc模式下必须遵照的一些隐式的规则显示的表达出来并放到了编译环境中,从编译时便避免了内存问题的发生。arc模式下显示的定义了强引用与弱引用,并用将相关的规则集成到其中。强引用被定义为strong指针,而弱引用则被定义为weak指针。strong指针的含议是,对一个对象持有引用而且有一个属于它的引用计数。strong指针不能被release,但当一个strong指针被置为nil的时候,相应的retainCount也会被减去。相应的weak指针也不能再对引用计数作任何的操做,由于它没有属于本身的引用计数。同时,当一weak指针所指向的对向被消毁的时候,这个weak指针也会被置空--这是一项重要的特性,它保证了弱引用指针不能去引用一个不可用的对象。 实际上,arc模式并非在运行的时候被执行的--它是一个编译过程。编译器在编译的过程当中,自动的在合适的地方插入retain,release等代码。
关于autorelease:oop
面试中常见的一个问题是:autorelease对象何时该用何时不应用,以及何时被释放。首先解释一下什么是autorelease。手动对一个对象发送release消息会致使该对象的引用计数马上被减一。而autorelease则会在未来的某一刻对该对象发送一个release消息。实际上被加了autorelease消息的对象会被放到autorelease pool中,而该pool在释放时,会对放到其中的对象发送一次release消息。这个说法是官方的说法,实际上我认为放到autorelease pool中这个说法是不许确的--对于两次放到同一个pool的同一个对象,pool会怎么作?实际上咱们能够认为,autorelease pool是一个链表,或者一个数组,每个被发送autorelease pool消息的对象的指针都会被加入到autorelease pool结构中,而当autorelealse pool释放的时候,这些指针也都会收到一次release消息。而屡次另入其中的对象实际上也会被释放屡次。 那么下一个问题就是,autorelease对象什么时候被释放?哈哈!这个问题是不专业的。实际上咱们应该问的是autorelease pool什么时候对其中的对象发送release消息?苹果文档告诉咱们,在每一次run loop结束时,autorelease pool都会被drain一次,一次点击,触摸,均可以是一次run loop。这样说彷佛很很差理解,让咱们换一种说法。咱们想象整个程序都是被一个while循环驱动的,在每一次while循环中,程序不断接收事件,而后交给相应的对象来处理。每一次循环,都是一次run loop。而autorelease pool,则能够理解为这个循环中的对象管理器,每一次循环中所产生的autorelease对象都被它记录,循环完的时候,对这些对象进行一次release。
(void)viewDidLoad
{
[super viewDidLoad]; [self test]; NSLog(@"%@", testString);
}
(void)test
{
testString = [[[NSString alloc] initWithFormat:@"aaaaaa"] autorelease];
[self test1];
}
(void)test1
{
NSLog(@"%@", testString);
}
这两个连续调用并无走出一个run loop的范围,因此没有引起内存错误。
还有一个问题:何时该显示建立autorelease pool?为何只有一个autorelease pool?这个问题太简单,不解释。