一个问题:关于类型转换Type Cast(汇编讲解 as 语法)
问题如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
TBase = class end; TChild = class(TBase) public F1:Integer; procedure Say; end;implementation{$R *.dfm}procedure TForm3.FormCreate(Sender: TObject);var A:TBase; B:TChild;begin A:=TBase.Create; try B:=A as TChild;//编译成功,但是运行报错 B.Say; finally A.Free; end;end;{ TChild }procedure TChild.Say;begin ShowMessage('%D',[F1]);end; |
首先,为什么会报错?编译成功代表语法没有问题.
我们看看As 是怎么实现的?
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
function _AsClass(Child: TObject; Parent: TClass): TObject;{$IFDEF PUREPASCAL}begin Result := Child; if not (Child is Parent) then Error(reInvalidCast); // loses return addressend;{$ELSE}asm { -> EAX left operand (class) } { EDX VMT of right operand } { <- EAX if left is derived from right, else runtime error } TEST EAX,EAX//如果对象是Nil就退出 JE @@exit MOV ECX,EAX@@loop: MOV ECX,[ECX]//获取自己的类型 CMP ECX,EDX//与要转换的类型进行比较 JE @@exit//一样就退出 MOV ECX,[ECX].vmtParent//不一样就取父类来比较 TEST ECX,ECX//判断父类是否为空. JNE @@loop { do runtime error } MOV AL,reInvalidCast//如果都不能匹配就报错 JMP Error@@exit:end;{$ENDIF} |
可以看到As会对类型进行一些列要求,而且是必须的.
如果我们把代码改一下用强制类型转换看看:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
procedure TForm3.FormCreate(Sender: TObject);var A:TBase; B:TChild;begin A:=TBase.Create; try B:=TChild(A);//没有错误 B.Say;//但是 弹出来的数据非0 finally A.Free; end;end; |
现在运行不会错了,但是弹出来的数据却不是0,为什么?成员变量会初始化的,那么如果创建一个TChild对象的话,
F1就应该是0,不管我们写没有写F1:=0;
要解释这个就需要用到我们之前的知识了.
正常情况下,A的内存:
| 偏移 | 0-3 | 4-7 |
| 内容 | TBase的地址 | $00000000 |
正常情况下,B的内存:
| 偏移 | 0-3 | 4-7 | 8-B |
| 内容 | TChild地址 | $00000000 | F1变量的值 |
也就是F1位于对象地址后面8个字节处.
那么上面的代码中,我们TChild.Say; 会用到F1,而我们把A当成TChild的实例了,是吧?那么去找F1,它就会跑到A+8的地方去,
但是我们看见实际A+8的地方不属于A管,所以这4个字节是未知的,没有被初始化成0,所以报出来也不太可能是0了.
谁叫A是下黑手去抢的内存.
从上面我们可以看到直接强制类型转换速度效率会快一些,所以我们在明白这样转换不会出问题就多用这样转换,但是这中间缺少检验的过程,所以有时候转换后结果可能会错误.
所以我们需要注意了:
|
1
2
|
If Sender Is TButton then TButton(Sender).XXX;//别再用Sender As TButton了,都判断过了 |
好,今天就唠叨到这里,我是DH.
一个问题:关于类型转换Type Cast(汇编讲解 as 语法)的更多相关文章
- c++类型转换Type Cast)
C风格的强制类型转换(Type Cast)很简单,不管什么类型的转换统统是:TYPE b = (TYPE)a.C++风格的类型转换提供了4种类型转换操作符来应对不同场合的应用. const_cast, ...
- C语言ASM汇编内嵌语法
转载:http://www.cnblogs.com/latifrons/archive/2009/09/17/1568198.html C语言ASM汇编内嵌语法 .3 GCC Inline ASM G ...
- JS对象 四舍五入round() round() 方法可把一个数字四舍五入为最接近的整数。 语法: Math.round(x)
四舍五入round() round() 方法可把一个数字四舍五入为最接近的整数. 语法: Math.round(x) 参数说明: 注意: 1. 返回与 x 最接近的整数. 2. 对于 0.5,该方法将 ...
- 打开新窗口(window.open) open() 方法可以查找一个已经存在或者新建的浏览器窗口。 语法: window.open([URL], [窗口名称], [参数字符串])
打开新窗口(window.open) open() 方法可以查找一个已经存在或者新建的浏览器窗口. 语法: window.open([URL], [窗口名称], [参数字符串]) 参数说明: URL: ...
- 类型强转(type cast)
类型转换有 c 风格的,当然还有 c++风格的.c 风格的转换的格式很简单(TYPEEXPRESSION),但是 c 风格的类型转换有不少的缺点,有的时候用 c 风格的转换是不合适的, 因为它可以在任 ...
- MySQL数据类型转换函数CAST与CONVERT的用法
MySQL 的CAST()和CONVERT()函数可用来获取一个类型的值,并产生另一个类型的值.两者具体的语法如下: 1.CAST(value as type) 就是CAST(xxx AS 类型) 2 ...
- mysql 的类型转换函数cast的用法
CAST(expr AS type), CONVERT(expr,type) , CONVERT(expr USING transcoding_name) CAST() ...
- nasm汇编讲解
一.什么是nasm汇编 nasm使用在windows.linux等系统下的汇编. 二.语法介绍 2.1 nasm 是区分大小写 例如:符号 foo 与 FOO 是两个不同的标识符. 2.2 内存操作数 ...
- $.ajax通路RESTful Web Service一个错误:Unsupported Media Type
最近项目,使用头版jquery ajax访问背景CXF发布时间rest维修,结果遇到了错误"Unsupported Media Type". 公布的服务java代码例如以下: im ...
随机推荐
- Robot Framework学习路线
0. 官方网站 http://robotframework.org/ 所有资料都来自这里,从这里找到必要的链接,从而深入其中的细节. 1. Quick Start Guide https://co ...
- iOS中的图像处理(三)——混合运算
有时候,单独对一张图像进行处理是很难或者根本达不到我们想要的效果的.一个好的滤镜效果的诞生,往往要经过很多复杂步骤.细致微调.图片应用效果观察以及很多图层叠加. 我在JSWidget上发现了一些常用混 ...
- 我写的一个 Qt 显示图片的控件
Qt 中没有专门显示图片的控件.通常我们会使用QLabel来显示图片.可是QLabel 显示图片的能力还是有点弱.比方不支持图像的缩放一类的功能.使用起来不是非常方便. 因此我就自己写了个简单的类. ...
- Read and Write NSArray, NSDictionary and NSSet to a File
查询地址:http://iosdevelopertips.com/data-file-management/read-and-write-nsarray-nsdictionary-and-nsset- ...
- BestCoder Round #57 (div.2)
第一场BC...感觉还是多参加点比赛吧... 第一题水题各种乱搞就可以过 第二题依旧水题..记个前缀和就行了.. 虽说是2道水题..然而我T1提交时就过了20min, T2还RE了一发..第二次提交就 ...
- Python 2.7 学习笔记 列表的使用
同其它编程语言一样,python也提供了丰富的数据结构,以方便数据的处理.本文介绍两种最基本的数据集合,列表和元组的使用. 一.列表使用介绍 可以理解为一个有序的序列.其使用方式举例如下: list= ...
- 常见makefile写法
原文地址:blog.csdn.net/ghostyu/article/details/7755177 1.目标名称,摆脱手动设置目标名称 TARGET = $(notdir $(CURDIR)) al ...
- LVS:DR模式(Direct Routing)部署实验
本文介绍怎样在kvm的虚拟环境下,部署实验LVS的DR模式.包含网络结构图,怎样配置.以及使用tcpdump分析ip包. 网络结构图 kvm ...
- iOS WebCore的WebEvent和EventHandler
WebEvent是iOS专有的类,负责封装和携带从UIKit得到的系统事件信息,并由WebKit层的WAKResponder子类传递到WebCore的EventHandler. UIKit层的逻辑可参 ...
- 网页制作之html基础学习4-格式与布局
1.position:fixed 锁定位置(相对于浏览器的位置),例如有些网站的右下角弹窗 例: <head> <title>123</title> <sty ...