Objective-c 对象是否都是相同类型的 C 结构? [英] Are objective-c objects all same type of C-structure?

查看:66
本文介绍了Objective-c 对象是否都是相同类型的 C 结构?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道该语言的面向对象特性是如何在 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

objstr 都可以强制转换为 objc_object *,也就是说这两个变量都是同类型的指针,不是吗?>

已解决

明白了!我误解了指针转换的工作原理.objstr 是不同结构类型的指针,但它们通常在内存前面都有类类型成员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 中的另一个根类.NSObjectNSProxy 的子类可以添加自己的实例变量,这些实例变量会附加到父类的结构中.

<块引用>

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

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

idvoid * 非常相似.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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆