返回

Objective-C 对象的本质

IOS

在面向对象编程中,对象是系统中的基本组成单元,它将数据和行为封装在一起,使用起来更加灵活和方便。那么,Objective-C 对象的本质是什么呢?

从 C++ 对象的本质入手

在 C++ 中,对象本质上是一种结构体,它由数据成员和成员函数组成。例如,下面是一个简单的 C++ 类:

class Person {
public:
    string name;
    int age;

    void eat() {
        cout << "Person is eating" << endl;
    }
};

我们可以通过以下命令将该类编译成目标文件:

clang -c Person.cpp

然后,我们可以使用 nm 命令查看目标文件中的符号表:

nm Person.o

输出结果如下:

0000000000000000 T _ZTV6Person
0000000000000000 T _ZTT6Person
0000000000000000 t _ZN6PersonC1Ev
0000000000000000 t _ZN6PersonC2ESs
0000000000000000 t _ZN6PersonD0Ev
0000000000000000 w _ZN6PersonD1Ev
0000000000000000 D _ZN6PersonE

可以看到,目标文件中包含了三个特殊的符号:_ZTV6Person_ZTT6Person_ZN6PersonE。这些符号是 C++ 编译器生成的,用于类的类型信息和虚函数表。

Objective-C 对象的本质

Objective-C 对象的本质也类似于 C++ 对象,它也是由数据成员和成员函数组成。但是,Objective-C 对象还有额外的成员,称为 isa 指针。isa 指针指向该对象的类对象。

我们可以通过以下命令将一个 Objective-C 类编译成目标文件:

clang -c Person.m

然后,我们可以使用 nm 命令查看目标文件中的符号表:

nm Person.o

输出结果如下:

0000000000000000 T _OBJC_CLASS_$_Person
0000000000000000 T _OBJC_METACLASS_$_Person
0000000000000000 t _OBJC_IVAR_$_Person._age
0000000000000000 t _OBJC_IVAR_$_Person._name
0000000000000000 t _OBJC_CLASS_$_NSObject
0000000000000000 t _class_Person
0000000000000000 t _meth_Person.age
0000000000000000 t _meth_Person.eat
0000000000000000 t _meth_Person.init
0000000000000000 w _objc_msgSend
0000000000000000 D _OBJC_CLASS_Person

可以看到,目标文件中包含了更多的特殊符号,这些符号是 Objective-C 编译器生成的,用于类的元信息、实例变量和方法。

NSObject 的底层

NSObject 是 Objective-C 中的所有类的基类,它定义了一些基本的方法,比如 allocinitrelease。我们可以通过以下命令将 NSObject 类编译成目标文件:

clang -c NSObject.m

然后,我们可以使用 nm 命令查看目标文件中的符号表:

nm NSObject.o

输出结果如下:

0000000000000000 T _OBJC_CLASS_$_NSObject
0000000000000000 T _OBJC_METACLASS_$_NSObject
0000000000000000 t _OBJC_IVAR_$_NSObject._class
0000000000000000 t _class_NSObject
0000000000000000 t _meth_NSObject.alloc
0000000000000000 t _meth_NSObject.class
0000000000000000 t _meth_NSObject.copy
0000000000000000 t _meth_NSObject.dealloc
0000000000000000 t _meth_NSObject.description
0000000000000000 t _meth_NSObject.finalize
0000000000000000 t _meth_NSObject.hash
0000000000000000 t _meth_NSObject.init
0000000000000000 t _meth_NSObject.initialize
0000000000000000 t _meth_NSObject.isEqual
0000000000000000 t _meth_NSObject.isKindOfClass
0000000000000000 t _meth_NSObject.isMemberOfClass
0000000000000000 t _meth_NSObject.performSelector
0000000000000000 t _meth_NSObject.release
0000000000000000 t _meth_NSObject.retain
0000000000000000 t _meth_NSObject.retainCount
0000000000000000 t _meth_NSObject.self
0000000000000000 w _objc_msgSend
0000000000000000 D _OBJC_CLASS_NSObject

可以看到,NSObject 类的目标文件中包含了更多的特殊符号,这些符号是 Objective-C 编译器生成的,用于描述类的元信息、实例变量和方法。

id 类型的本质

在 Objective-C 中,id 类型是一个特殊的类型,它可以指向任何对象。实际上,id 类型的本质就是 objc_object *。我们可以通过以下命令将 objc_object.h 文件中的 objc_object 结构体打印出来:

cat /usr/include/objc/objc_object.h | grep struct\ objc_object

输出结果如下:

struct objc_object {
    Class isa;
};

可以看到,objc_object 结构体只有一个成员变量:isa 指针。因此,我们可以得出结论:id 类型的本质就是 objc_object *

总结

通过本文的分析,我们可以得出以下结论:

  • Objective-C 对象的本质类似于 C++ 对象,它也是由数据成员和成员函数组成。
  • Objective-C 对象还有额外的成员,称为 isa 指针,isa 指针指向该对象的类对象。
  • NSObject 是 Objective-C 中的所有类的基类,它定义了一些基本的方法,比如 allocinitrelease
  • id 类型的本质就是 objc_object *