objective-c对象是否都是相同类型的C结构?

时间:2013-05-28 03:46:40

标签: objective-c runtime

我想知道语言的面向对象特性是如何在C中实现的。

正如<objc/runtime.h>中所定义的,id类型是指向objc_object的指针,而objc_object类型是仅包含一个成员{C} {1}}的C结构存储isa。那么存储任何对象的实例变量的实际值的位置和方式是什么?

另外一件事是,所有Objective-C对象指针都可以转换为Class(这是一个指向C结构的指针,其中不存在继承等特性)是Objective-C class只是编译器的限定符,所有实例都是id的同类型的?

加入:

objc_object

此代码编译并输出:

NSObject *obj = [NSObject new];
objc_object *objStruct = (__bridge objc_object *)obj;
NSLog(@"obj: %@", NSStringFromClass(objStruct->isa));

NSString *str = [NSString new];
objc_object *strStruct = (__bridge objc_object *)str;
NSLog(@"str: %@", NSStringFromClass(strStruct->isa));

obj: NSObject, str: __NSCFConstantString obj都可以转换为str,这意味着两个变量都是同一类型的指针,不是吗?

解决

明白!我误解了指针投射是如何工作的。 objc_object *obj是不同结构类型的指针,但两者通常在内存前面都有类型成员str,因此可以视为isa 。下面的代码模仿了这个机制:

objc_object

谢谢!

1 个答案:

答案 0 :(得分:5)

  

那么存储实例变量的实际值的位置和方式是什么?

它们始终存放在同一个地方 - 在对象内部。如你所说,id表示指向任何类型对象的指针。但是,除此之外,它没有定义任何特定类型 - 它没有说明对象的实际类型。

objc_object只是一种基本类型,相当于NSObject。看一下NSObject.h,您会看到NSObject的实例有一个实例变量isa指针。 NSProxy也是如此,它是Objective-C中的另一个根类。 NSObjectNSProxy的子类可以添加自己的实例变量,这些变量将附加到父结构中。

  

如果所有Objective-C对象指针都可以转换为   id,所有Objective-C类都只是编译器的限定符,并且   在运行时所有这些实例同样类型的objc_object?

我不确定你在这里问的是什么。编译器不会阻止你向任何对象发送任何消息(虽然如果它认为你正在向不支持它的对象发送消息它会发出警告),所以在某种意义上编译器并不关心关于各种对象类型。另一方面,不同类型的对象不同 - 并不是所有类都转换为的通用类型。

idvoid *强烈相似。 void *是一个通用指针,您可以将任何指针强制转换为void *,但这并不意味着所有指针都是等效的。 id与添加的限制几乎相同,即您为类型id的变量指定的指针必须指向Objective-C对象。