swift class的虚函数表、扩展、@objc修饰、虚函数的派发方式研究
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) -> ()
class_method
: 该指令通过类的函数表来查找函数, 基于类的实际类型.apply
: 传递参数并执行函数.
作者:MaizeJS
链接:https://www.jianshu.com/p/cfe7da01880d
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
swift class的虚函数表、扩展、@objc修饰、虚函数的派发方式研究的更多相关文章
- C++ 虚函数表解析
转载:陈皓 http://blog.csdn.net/haoel 前言 C++中 的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实 ...
- 对C++虚函数、虚函数表的简单理解
一.虚函数的作用 以一个通用的图形类来了解虚函数的定义,代码如下: #include "stdafx.h" #include <iostream> using name ...
- C++的虚函数表
这里的例子全部来自陈皓的C++ 虚函数表解析,经过修改的. 编译器:g++ (Ubuntu 4.9.2-10ubuntu13) 4.9.2 环境:ubuntu 15.04 64位系统(地址占8字节) ...
- 我理解的C++虚函数表
今天拜读了陈皓的C++ 虚函数表解析的文章,感觉对C++的继承和多态又有了点认识,这里写下自己的理解.如果哪里不对的,欢迎指正.如果对于C++虚函数表还没了解的话,请先拜读下陈皓的C++ 虚函数表解析 ...
- C++虚函数表原理
C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指 向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的指针有“多种形态”,这是一种泛型技 ...
- C++ 虚函数表解析(转载)
转载自:陈皓 http://blog.csdn.net/haoel/article/details/1948051/ 前言 C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型 ...
- 转载:C++ 虚函数表解析
目录(?)[+] 转载:http://blog.csdn.net/haoel/article/details/1948051# 前言 C++中 的虚函数的作用主要是实现了多态的机制.关于多态,简而 ...
- C++ 虚函数表与内存模型
1.虚函数 虚函数是c++实现多态的有力武器,声明虚函数只需在函数前加上virtual关键字,虚函数的定义不用加virtual关键字. 2.虚函数要点 (1) 静态成员函数不能声明为虚函数 可以这么理 ...
- C++虚函数及虚函数表解析
一.背景知识(一些基本概念) 虚函数(Virtual Function):在基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数.纯虚函数(Pure Virtual Functio ...
随机推荐
- 【手记】解决“未能创建 SSL/TLS 安全通道”异常
之前写了一个桌面程序,程序会间歇性访问某个https接口,一直用的好好的,今天突然报错了,异常就发生在访问接口的地方,曰“请求被中止,未能创建 SSL/TLS 安全通道.”,另外有台电脑也有跑该程序, ...
- 在服务器上搭建wordpress个人博客 php7.2+nginx+mysql+wordperss
买了台VPS,准备搭建一个博客.用过几个博客框架还是觉得Wordpress好用.主题多,插件也非常的便利,而且大多还免费开源.搭建也很简单,其实安装好php+mysql+nginx+wordpress ...
- sql 去掉 空格
一.问题描述: 数据库中字段 nvarchar类型 存放数据如下: '3.3×10' 二.解决方案: --测试用例CREATE TABLE #temp(NAME NVARCHAR(20) null) ...
- WebService学习概念总结
概念总结:WebSerevice是一种跨编程语言和跨操作系统平台的远程调用技术传输协议:HTTP技术构成:XML+XSD,SOAP,WSDL XML封装数据格式,解决数据表示问题 XSD定 ...
- js 日期格式转换(转载)
1.当前时间转为 “yyyy-MM-dd HH:MM:SS” function getNowFormatDate() { var date = new Date(); var seperator1 = ...
- Pseudocode MD5 CODE
//Note: All variables are unsigned 32 bit and wrap modulo 2^32 when calculating var int[64] s, K //s ...
- 基于python的websocket开发,tomcat日志web页面实时打印监控案例
web socket 接收器:webSocket.py 相关依赖 # pip install bottle gevent gevent-websocket argparse from bottle i ...
- Linux常用基本命令:三剑客命令之-awk输入输出分隔符
输入分隔符,英文原文为field separator,此处简称为FS,默认是空白字符(即空格),awk默认以空白字符为分隔符对每一行进行分割. 输出分割符,英文原文为output field sepa ...
- Python全栈学习_day002作业
Day2作业及默写 1.判断下列逻辑语句的True,False. 1)1 > 1 or 3 < 4 or 4 > 5 and 2 > 1 and 9 > 8 or 7 & ...
- c语言学习笔记-switch
我的邮箱地址:zytrenren@163.com欢迎大家交流学习纠错! 一.switch函数意义 选择性执行 二.switch函数结构 switch(表达式) { case: 常量表达式; 语句1; ...