Objective-c 对象是否都是相同类型的 C 结构? [英] Are objective-c objects all same type of C-structure?
问题描述
我想知道该语言的面向对象特性是如何在 C 中实现的.
如<objc/runtime.h>
中所定义,id
类型是一个指向objc_object
的指针,而objc_object
类型是一种 C 结构,只有一个成员 isa
存储一个 Class
.那么任何对象的实例变量的实际值存储在哪里以及如何存储?
还有一件事,所有objective-C对象指针都可以转换为id
(这是一个指向C结构的指针,其中不存在继承等特性),是Objective-C 类只是编译器的限定符,并且所有实例的 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
.下面的代码模仿了这种机制:
typedef struct {内部结构;Fake_NSObject;类型定义结构{内部结构;字符*字符串;Fake_NSString;Fake_NSObject obj = {1};Fake_NSObject *objPtr = &obj;NSLog(@"obj: %d", objPtr->isa);//打印 1Fake_NSString str = {2, "abc"};Fake_NSString *strPtr = &str;NSLog(@"str: %d", strPtr->isa);//打印 2Fake_NSObject *objPtr2 = (Fake_NSObject *)strPtr;//还行吧.NSLog(@"obj2: %d", objPtr2->isa);//打印 2Fake_NSString *strPtr2 = (Fake_NSString *)objPtr;//这是无效的,但仍然有效.NSLog(@"str2: %d", strPtr2->isa);//打印 1
谢谢!
那么它的实例变量的实际值存储在哪里以及如何存储?
它们一如既往地存储在同一个地方——对象内部.正如您所说,id
表示指向任何类型对象的指针.但是,除此之外,它没有定义任何特定类型——它没有说明对象的实际类型.
objc_object
只是一个等价于 NSObject
的基本类型.看看 NSObject.h,你会看到 NSObject
的实例有一个实例变量,isa
指针.NSProxy
也是如此,它是 Objective-C 中的另一个根类.NSObject
或 NSProxy
的子类可以添加自己的实例变量,这些实例变量会附加到父类的结构中.
如果所有objective-C对象指针都可以转换为id,所有的 Objective-C 类都只是编译器的限定符,并且在运行时,所有这些实例都是 objc_object 的类型吗?
我不确定你在这里问的是什么.编译器不会阻止您向任何对象发送任何消息(尽管如果它认为您正在向不支持它的对象发送消息,它会警告您),因此在某种意义上编译器并不关心关于各种对象类型.另一方面,不同类型的对象是不同的——没有所有类都转换成的通用类型.
id
与 void *
非常相似.void *
是一个通用指针,您可以将任何指针转换为 void *
,但这并不意味着所有指针都是等价的.id
与附加限制几乎相同,即您分配给 id
类型变量的指针必须指向一个 Objective-C 对象.
I want to know how the language's object-oriented features are implemented in C.
As defined in <objc/runtime.h>
, id
type is a pointer to a objc_object
, and objc_object
type is a C-structure with only one member isa
storing a Class
. Then where and how are the actual values of any object's instance-variables stored?
One more thing, the fact that all objective-C object-pointers can be casted to id
(which is a pointer to a C-structure, where no feature such as inheritance exists), are Objective-C classes just qualifiers for the compiler, and all instances equally type of objc_object
?
added:
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));
This code compiles and outputs:
obj: NSObject, str: __NSCFConstantString
Both obj
and str
can be casted to objc_object *
, which means both variables are pointers of a same type, no?
resolved
Understood! I was misunderstanding how pointer-casting works. obj
and str
are pointers of different structure-types, but both commonly have Class-type member isa
at the front of the memory, so can be treated as a objc_object
. The code below mimics this mechanism:
typedef struct {
int isa;
} Fake_NSObject;
typedef struct {
int isa;
char *string;
} Fake_NSString;
Fake_NSObject obj = {1};
Fake_NSObject *objPtr = &obj;
NSLog(@"obj: %d", objPtr->isa); // prints 1
Fake_NSString str = {2, "abc"};
Fake_NSString *strPtr = &str;
NSLog(@"str: %d", strPtr->isa); // prints 2
Fake_NSObject *objPtr2 = (Fake_NSObject *)strPtr; // this is ok.
NSLog(@"obj2: %d", objPtr2->isa); // prints 2
Fake_NSString *strPtr2 = (Fake_NSString *)objPtr; // this is invalid, but still works.
NSLog(@"str2: %d", strPtr2->isa); // prints 1
Thanks!
Then where and how are the actual values of it's instance-variables stored?
They're stored in the same place as always -- inside the object. As you say, id
represents a pointer to any kind of object. However, it doesn't define any specific type beyond that -- it doesn't say anything about the actual type of the object.
objc_object
is just a base type that's equivalent to NSObject
. Take a look at NSObject.h and you'll see that an instance of NSObject
has a single instance variable, the isa
pointer. The same is true for NSProxy
, which is another root class in Objective-C. Subclasses of NSObject
or NSProxy
can add their own instance variables, which are appended to the parent's structure.
if all objective-C object-pointers can be casted to id, are all Objective-C classes just qualifiers for the compiler, and at runtime all those instances equally type of objc_object?
I'm not sure what you're asking here. The compiler won't stop you from sending any message to any object (although it will warn you if it thinks you're sending a message to an object that doesn't support it), so in a sense the compiler doesn't care about the various object types. On the other hand, objects of different types are different -- there's not universal type that all classes are converted to.
id
is strongly analogous to void *
. void *
is a generic pointer, and you can cast any pointer to void *
, but that doesn't mean that all pointers are equivalent. id
is pretty much the same thing with the added restriction that the pointer you assign to a variable of type id
has to point to an Objective-C object.
这篇关于Objective-c 对象是否都是相同类型的 C 结构?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!