swift class的虚函数表、扩展、@objc修饰的研究

工具:

swiftc -emit-sil BaseClass.swift | xcrun swift-demangle > ClassFunc.silgen

cat ClassFunc.silgen

目标:

1、@objc和@objc dynamic修饰的函数是否进入虚函数表;

2、虚函数的的派发机制是什么?函数的调用在编译器层面最终转化为apply调用;

3、extension中的缺省修饰函数是否进入虚函数表;

4、extension中的@objc修饰函数的行为;

5、结构体是否允许@objc修饰:

@objc can only be used with members of classes, @objc protocols, and concrete extensions of classes

https://www.cnblogs.com/feng9exe/p/9460336.html

class NSObjectBase: NSObject {

func Msg_Normal(){ print("Msg_Normal") }

func Msg_Second(){ print("Msg_Second") }

func Msg_Third(){ print("Msg_Second") }

@objc func Msg_ObjcX(){}

@objc dynamic func Msg_Objc_Dynamic(){}

func callTest(){self.Msg_Normal()}

func callAgain(){self.Msg_Third()}

}

extension NSObjectBase{

@objc func OcExtensionFunc(){print("OcExtensionFunc")}

}

class DerivedOcClass:NSObjectBase{

override func OcExtensionFunc(){print("DerivedOcClass OcExtensionFunc")}

}

// NSObjectBase.Msg_Objc_DynamicX()

sil hidden @NSObjectBase.NSObjectBase.Msg_Objc_DynamicX() -> () : $@convention(method) (@guaranteed NSObjectBase) -> () {

// %0                                             // user: %1

bb0(%0 : $NSObjectBase):

debug_value %0 : $NSObjectBase, let, name "self", argno 1 // id: %1

%2 = tuple ()                                   // user: %3

return %2 : $()                                 // id: %3

} // end sil function 'NSObjectBase.NSObjectBase.Msg_Objc_DynamicX() -> ()'

// @objc NSObjectBase.Msg_Objc_DynamicX()

sil hidden [thunk] @@objc NSObjectBase.NSObjectBase.Msg_Objc_DynamicX() -> () : $@convention(objc_method) (NSObjectBase) -> () {

// %0                                             // users: %4, %3, %1

bb0(%0 : $NSObjectBase):

strong_retain %0 : $NSObjectBase                // id: %1

// function_ref NSObjectBase.Msg_Objc_DynamicX()

%2 = function_ref @NSObjectBase.NSObjectBase.Msg_Objc_DynamicX() -> () : $@convention(method) (@guaranteed NSObjectBase) -> () // user: %3

%3 = apply %2(%0) : $@convention(method) (@guaranteed NSObjectBase) -> () // user: %5

strong_release %0 : $NSObjectBase               // id: %4

return %3 : $()                                 // id: %5

} // end sil function '@objc NSObjectBase.NSObjectBase.Msg_Objc_DynamicX() -> ()'

// NSObjectBase.Msg_ObjcX()

sil hidden @NSObjectBase.NSObjectBase.Msg_ObjcX() -> () : $@convention(method) (@guaranteed NSObjectBase) -> () {

// %0                                             // user: %1

bb0(%0 : $NSObjectBase):

debug_value %0 : $NSObjectBase, let, name "self", argno 1 // id: %1

%2 = tuple ()                                   // user: %3

return %2 : $()                                 // id: %3

} // end sil function 'NSObjectBase.NSObjectBase.Msg_ObjcX() -> ()'

// @objc NSObjectBase.Msg_ObjcX()

sil hidden [thunk] @@objc NSObjectBase.NSObjectBase.Msg_ObjcX() -> () : $@convention(objc_method) (NSObjectBase) -> () {

// %0                                             // users: %4, %3, %1

bb0(%0 : $NSObjectBase):

strong_retain %0 : $NSObjectBase                // id: %1

// function_ref NSObjectBase.Msg_ObjcX()

%2 = function_ref @NSObjectBase.NSObjectBase.Msg_ObjcX() -> () : $@convention(method) (@guaranteed NSObjectBase) -> () // user: %3

%3 = apply %2(%0) : $@convention(method) (@guaranteed NSObjectBase) -> () // user: %5

strong_release %0 : $NSObjectBase               // id: %4

return %3 : $()                                 // id: %5

} // end sil function '@objc NSObjectBase.NSObjectBase.Msg_ObjcX() -> ()'

sil hidden @NSObjectBase.NSObjectBase.callTest() -> () : $@convention(method) (@guaranteed NSObjectBase) -> () {

// %0                                             // users: %3, %2, %1

bb0(%0 : $NSObjectBase):

debug_value %0 : $NSObjectBase, let, name "self", argno 1 // id: %1

%2 = class_method %0 : $NSObjectBase, #NSObjectBase.Msg_Normal!1 : (NSObjectBase) -> () -> (), $@convention(method) (@guaranteed NSObjectBase) -> () // user: %3

%3 = apply %2(%0) : $@convention(method) (@guaranteed NSObjectBase) -> ()

%4 = tuple ()                                   // user: %5

return %4 : $()                                 // id: %5

} // end sil function 'NSObjectBase.NSObjectBase.callTest() -> ()'

// NSObjectBase.callAgain()

sil hidden @NSObjectBase.NSObjectBase.callAgain() -> () : $@convention(method) (@guaranteed NSObjectBase) -> () {

// %0                                             // users: %3, %2, %1

bb0(%0 : $NSObjectBase):

debug_value %0 : $NSObjectBase, let, name "self", argno 1 // id: %1

%2 = class_method %0 : $NSObjectBase, #NSObjectBase.Msg_Third!1 : (NSObjectBase) -> () -> (), $@convention(method) (@guaranteed NSObjectBase) -> () // user: %3

%3 = apply %2(%0) : $@convention(method) (@guaranteed NSObjectBase) -> ()

%4 = tuple ()                                   // user: %5

return %4 : $()                                 // id: %5

} // end sil function 'NSObjectBase.NSObjectBase.callAgain() -> ()'

sil_vtable NSObjectBase {

#NSObjectBase.Msg_Normal!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.Msg_Normal() -> () // NSObjectBase.Msg_Normal()

#NSObjectBase.Msg_Second!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.Msg_Second() -> () // NSObjectBase.Msg_Second()

#NSObjectBase.Msg_Third!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.Msg_Third() -> ()// NSObjectBase.Msg_Third()

#NSObjectBase.Msg_Objc!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.Msg_Objc() -> () // NSObjectBase.Msg_Objc()

#NSObjectBase.callTest!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.callTest() -> () // NSObjectBase.callTest()

#NSObjectBase.callAgain!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.callAgain() -> ()// NSObjectBase.callAgain()

}

sil_vtable DerivedOcClass {

#NSObjectBase.Msg_Normal!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.Msg_Normal() -> () [inherited] // NSObjectBase.Msg_Normal()

#NSObjectBase.Msg_Second!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.Msg_Second() -> () [inherited] // NSObjectBase.Msg_Second()

#NSObjectBase.Msg_Third!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.Msg_Third() -> () [inherited] // NSObjectBase.Msg_Third()

#NSObjectBase.Msg_Objc!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.Msg_Objc() -> () [inherited] // NSObjectBase.Msg_Objc()

#NSObjectBase.callTest!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.callTest() -> () [inherited] // NSObjectBase.callTest()

#NSObjectBase.callAgain!1: (NSObjectBase) -> () -> () : @NSObjectBase.NSObjectBase.callAgain() -> () [inherited] // NSObjectBase.callAgain()

}

apply担任函数绑定和派发的职责

那么阅读就显得简单多了, 可以看到最终对应到 testFunc函数调用的指令有两条.

%4 = class_method %2 : $MyClass, #MyClass.testFunc!1 : (MyClass) -> () -> (), $@convention(method) (@guaranteed MyClass) -> () // user: %5
%5 = apply %4(%2) : $@convention(method) (@guaranteed MyClass) -> ()
  1. class_method: 该指令通过类的函数表来查找函数, 基于类的实际类型.
  2. apply: 传递参数并执行函数.

作者:MaizeJS
链接:https://www.jianshu.com/p/cfe7da01880d
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

swift class的虚函数表、扩展、@objc修饰、虚函数的派发方式研究的更多相关文章

  1. C++ 虚函数表解析

    转载:陈皓 http://blog.csdn.net/haoel 前言 C++中 的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实 ...

  2. 对C++虚函数、虚函数表的简单理解

    一.虚函数的作用 以一个通用的图形类来了解虚函数的定义,代码如下: #include "stdafx.h" #include <iostream> using name ...

  3. C++的虚函数表

    这里的例子全部来自陈皓的C++ 虚函数表解析,经过修改的. 编译器:g++ (Ubuntu 4.9.2-10ubuntu13) 4.9.2 环境:ubuntu 15.04  64位系统(地址占8字节) ...

  4. 我理解的C++虚函数表

    今天拜读了陈皓的C++ 虚函数表解析的文章,感觉对C++的继承和多态又有了点认识,这里写下自己的理解.如果哪里不对的,欢迎指正.如果对于C++虚函数表还没了解的话,请先拜读下陈皓的C++ 虚函数表解析 ...

  5. C++虚函数表原理

    C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指 向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的指针有“多种形态”,这是一种泛型技 ...

  6. C++ 虚函数表解析(转载)

    转载自:陈皓 http://blog.csdn.net/haoel/article/details/1948051/ 前言 C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型 ...

  7. 转载:C++ 虚函数表解析

    目录(?)[+]   转载:http://blog.csdn.net/haoel/article/details/1948051# 前言 C++中 的虚函数的作用主要是实现了多态的机制.关于多态,简而 ...

  8. C++ 虚函数表与内存模型

    1.虚函数 虚函数是c++实现多态的有力武器,声明虚函数只需在函数前加上virtual关键字,虚函数的定义不用加virtual关键字. 2.虚函数要点 (1) 静态成员函数不能声明为虚函数 可以这么理 ...

  9. C++虚函数及虚函数表解析

    一.背景知识(一些基本概念) 虚函数(Virtual Function):在基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数.纯虚函数(Pure Virtual Functio ...

随机推荐

  1. Electron学习(一)——— electron的安装

    前言 本人是做java开发的(菜鸟),做web项目的朋友们基本上都会遇到同样一个,永远不知道客户会怎么样使用,或者说永远不知道客户会用什么浏览器打开我们做出来的应用,就算你跟他说明了一定得用某某某浏览 ...

  2. 使用Asp.Net Core MVC 开发项目实践[第三篇:基于EF Core的扩展]

    上篇我们说到了EFCore的基础使用,这篇我们将讲解下基于EFCore的扩展. 我们在Mango.Framework.EFCore类库项目中创建一个类名EFExtended的扩展类,并且引入相关的命名 ...

  3. angularjs学习第四天笔记(第一篇:简单的表单验证)

    您好,我是一名后端开发工程师,由于工作需要,现在系统的从0开始学习前端js框架之angular,每天把学习的一些心得分享出来,如果有什么说的不对的地方,请多多指正,多多包涵我这个前端菜鸟,欢迎大家的点 ...

  4. 同源策略与CORS

    同源策略 同源策略是浏览器保护用户安全上网的重要措施,协议.域名.端口号三者相同即为同源. 不同源下,浏览器不允许js操作Cookie.LocalStorage.DOM等数据或页面元素,也不允许发送a ...

  5. mapreduce的cleanUp和setUp的特殊用法(TopN问题)和常规用法

    一:特殊用法 我们上来不讲普通用法,普通用法放到最后.我们来谈一谈特殊用法,了解这一用法,让你的mapreduce编程能力提高一个档次,毫不夸张!!!扯淡了,让我们进入正题: 我们知道reduce和m ...

  6. Jquery Ajax 调用后台并返回数据

    一.前台调用ajax并解析json对象. $.ajax({ url : '', type : 'POST', //GET data : '’, beforeSend : function(reques ...

  7. Java-关于类

    java-关于类-成员初始化问题 成员初始化出现错误“    - Syntax error on token ";", , expected” java类不允许对成员进行操作,但可 ...

  8. 【RabbitMQ】6、rabbitmq生产者的消息确认

    通过Publisher Confirms and Returns机制,生产者可以判断消息是否发送到了exchange及queue,而通过消费者确认机制,Rabbitmq可以决定是否重发消息给消费者,以 ...

  9. Apache SkyWalking的架构设计【译文】

    Apache SkyWalking提供了一个功能强大并且很轻量级的后端.在此,将介绍为什么采用以下方式来设计它,以及它又是如何工作的. 架构图 对于APM而言,agent或SDKs仅是如何使用libs ...

  10. CloudSim源代码学习——服务代理商(DatacenterBroker)

    DatacenterBroker.java文件如下: (其中,相关语句已经做好标注) /* * Title: CloudSim Toolkit * Description: CloudSim (Clo ...