多态
父类指针指向子类对象
- Swift 中多态的实现类似于 c++ 中的虚表
- OC 多态实现利用的是 Runtime
struct 与 class 调用函数的差异
从汇编看出,struct实例调用的函数都均在代码区的固定位置
class实例调用函数代码位置不固定,在方框处 si 进入,可以看到对应的是 animal.speck函数
汇编分析
class Animal {
func speak() { print("animal speak") }
func eat() { print("animal run") }
func sleep() { print("animal sleep") }
}
class Dog: Animal {
override func speak() { print("dog speak") }
override func eat() { print("dog run") }
func run() { print("run") }
}
var animal: Animal
animal = Animal()
animal.speak() // animal speak
animal.eat() // animal run
animal.sleep() // animal sleep
animal = Dog()
animal.speak() // dog speak
animal.eat() // dog run
animal.sleep() // animal sleep
-
从汇编中可以看到一共调用了三个不确定位置的函数,分别是
callq *0x50(%rax)
、callq *0x58(%rax)
、callq *0x60(%rax)
,分别对应 speck、eat、sleep
-
倒推发现,callq 所依赖的 rax 是 animal 的指针,指向的是所申请的堆空间对象。通过堆空间地址 + 固定偏移量来找到对应函数。
多态的实现:将要调用父类还是子类的对应函数,这些信息都在编译时确定,保存于对象的类型信息中,位于全局区,调用时底层会去查询。
-
同类对象的类型信息是同一块。