16,748
社区成员
发帖
与我相关
我的任务
分享
unit main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TSimpleTest = class
private
public
procedure PrintClassName;
function DoubleValue(AValue: Double): Double;
end;
TForm1 = class(TForm)
btn1: TButton;
procedure btn1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.btn1Click(Sender: TObject);
var
SimpleTest: TSimpleTest;
i: Double;
begin
//这里置为nil
SimpleTest := nil;
SimpleTest.PrintClassName;
i := 5;
i := SimpleTest.DoubleValue(I);
ShowMessage(FloatToStr(I));
if not Assigned(SimpleTest) then
ShowMessage('Object is nil!');
end;
{ TSimpleTest }
function TSimpleTest.DoubleValue(AValue: Double): Double;
begin
Result := AValue * 2;
end;
procedure TSimpleTest.PrintClassName;
begin
//这里必须用类方法,否则就报错
ShowMessage(TSimpleTest.ClassName);
end;
end.
Type
TTestClass = class(TComponent)
public
Function GetThisClassName : AnsiString;
end;
function TTestClass.GetThisClassName: AnsiString;
begin
Result := Self.ClassName;
//Result := ClassName; 这和上一句就本次访问的内容来说是一回事
//ClassName好象特殊了一点,反正就是为了说明这事
end;
procedure TForm1.FormCreate(Sender: TObject);
var
Obj : TTestClass;
begin
Obj := TTestClass(TObject.Create);
//这样调用,相当于让类中引用Self的地方都变成引用这个Obj对象,即TObject的实例
//注意类方法/函数中引用类自身的或者父类的数据定义,都是隐含的Self引用
if Obj.GetThisClassName = 'TObject' then
ShowMessage('相等');
end;
procedure TForm1.btn1Click(Sender: TObject);
var
p: Pointer;
begin
p := @TSimpleTest.PrintClassName;
asm
MOV EAX, 0
CALL p
end;
end;
unit Unit3;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm3 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form3: TForm3;
implementation
{$R *.dfm}
type
Ta = class
f: char;
procedure a;
procedure b;
end;
{ Ta }
procedure Ta.a;
begin
f := 'f';//访问数据成员
ShowMessage('a');
end;
{procedure Ta.a对应的汇编代码:
Unit3.pas.36: f := 'f';
0045C028 C6400466 mov byte ptr [eax+$04],$66
//eax+$04是数据成员f的地址,此时因为eax=0,所以地址为4,显然是个非法的地址,会报错
Unit3.pas.37: ShowMessage('a');
0045C02C B840C04500 mov eax,$0045c040//字符串'a'所在的地址
0045C031 E82611FDFF call ShowMessage//调用ShowMessage
Unit3.pas.38: end;
0045C036 C3 ret//返回
}
procedure Ta.b;
begin
ShowMessage('b');
end;
{procedure Ta.b对应的汇编代码:
Unit3.pas.42: ShowMessage('b');
0045C044 B858C04500 mov eax,$0045c058//字符串'b'所在的地址
0045C049 E80E11FDFF call ShowMessage//调用ShowMessage
Unit3.pas.43: end;
0045C04E C3 ret//返回
}
procedure TForm3.FormCreate(Sender: TObject);
var
o: Ta;
begin
o := nil;
o.b;//此行正常执行
o.a;//此行报错
end;
{procedure TForm3.FormCreate对应的汇编代码:
Unit3.pas.48: begin
0045C05C 53 push ebx//保存ebx
Unit3.pas.49: o := nil;
0045C05D 33DB xor ebx,ebx//清空ebx,这时ebx等于0
Unit3.pas.50: o.b;
0045C05F 8BC3 mov eax,ebx//将ebx的值赋予eax,这时eax也等于0
0045C061 E8DEFFFFFF call Ta.b//调用类Ta的方法b
Unit3.pas.51: o.a;
0045C066 8BC3 mov eax,ebx//eax等于0
0045C068 E8BBFFFFFF call Ta.a//调用类Ta的方法a
Unit3.pas.52: end;
0045C06D 5B pop ebx//恢复ebx
0045C06E C3 ret//返回
}
end.
#include <iostream>
class A
{
public:
void foo(void) const { std::cout << "called function 'foo'." << std::endl; };
};
int main(void)
{
A * p = nullptr;
p->foo(); //p为空指针,本来是不允许的。这样调用居然没有错。
return(0);
}