分享
 
 
 

《Mastering Delphi 6》学习笔记之五

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

《Mastering Delphi 6》 学习笔记之五

在某个类中用protected声明的变量,在本单元之外是不能够随意访问的(通过声明子类才可以访问其protected域)。《Mastering Delphi 6》中提到了一个不常用的技巧:

// Unit2

type TTest = class

protected

protectedVar : integer;

end;

// Unit1

type

TFake = class(TTest);

procedure TForm1.FormCreate(Sender:TObject);

var

Test : TTest;

begin

Test := TTest.Create;

// Test.protectedVar := 1; // not work!

TFake(Test).protectedVar := 1; // This works!

Test.Free;

end;

当然了,你也可以向TFake添加代码来实现同样的功能,但是上述方法的好处在于只需要一个占位符,而不需要为修改一个变量而大动干戈的派生一个类。在实际中这个技巧很少会用到,不过既然作者提到了,还是记以备考.

用来声明虚拟函数的关键字,在C++中只要一个virtual就可以了,不论是在基类还是派生类中。但是在Delphi中,一定要记住:在基类中使用virtual,在派生类中使用override。如果忘记了这一点的话,会导致两个后果:

1.编译程序的时候会得到一个“Method ‘XXX’hides the virtual method of base type ‘XXX’”(尽管程序还可以运行);

2.多态机制将无法正常工作。例如,

type

TAnimal=class

procedure Voice;virtual;

end;

TDog=class(TAnimal)

procedure Voice;virtual;

end;

implementation

procedure TAnimal.Voice;

begin

ShowMessage(‘Animal Voice’);

end;

procedure TDog.Voice;

begin

ShowMessage(‘Dog Voice’);

end;

procedure TForm1.FormCreate(Sender:TObject);

var

a : TAnimal;

begin

a := TAnimal.Create;

a.Voice;

a.Free;

a := TDog.Create;

a.Voice;

a.Free;

end;

运行这个程序的话,你会得到两个‘Animal Voice’。只要将声明中第二个virtual 改为override,你就能得到正确的结果:一个’Animal Voice’ 和一个’Dog Voice’。

在C++中,只要基类中的函数声明为virtual,那么派生类中的同名函数也会自动成为virtual。那么Object Pascal中的override关键字是不是多此一举呢?《Mastering Delphi 6》的作者是这样解释的:声明override表明你希望基类中一定有一个同名的virtual函数,从而可以避免常见的拼写错误。例如,在C++中,你在基类中写了一个名为Func的virtual函数,并且在派生类中重载了它。不幸的是,你不小心把Func拼成了Fund。编译器无法检查出这种错误。当你在程序中将一个基类指针指向一个派生类,并且希望它自动调用派生类的Func函数的时候,实际上只能是调用了基类的Func函数,而且这一类错误很难查找和排除。

嗯,听起来似乎确有道理。

dynamic和virtual之异同

dynamic和virtual不仅作用相同,声明的语法也相同。它们唯一不同的在于内部机制。virtual的实现是通过虚拟方法表(VMT,virtual method table,和C++中的vtbl很相似)实现的,在类中每一个虚拟函数在VMT中都要占用一个位置。VMT的一个不利之处在于,不论派生类中有没有重载基类中的方法,都不会改变VMT的大小,这样VMT中很多位置实际上是重复的,在一个比较大的类库中,势必要浪费不少内存。dynamic的实现方法有所不同,它不是通过VMT中指向实际方法的指针,而是通过索引来实现的,这样只有派生类中重载了的方法才会占据实际的表项,从而节省了内存。dynamic的不利之处在于,由于dynamic的方法表格(相对于VMT,dynamic的方法表格可以称为DMT)在基类和派生类中的大小不一定相同,同一个dynamic method的表项位置也不一定相同,所以dynamic方法必须动态查找,调用效率就低一些。相比而言,在基类和派生类中的virtual method在VMT中的表项位置总是固定的,所以调用很快。

总之,dynamic的优点就是virtual的缺点,dynamic的缺点也就是virtual的优点。你可以按照自己的需要来决定究竟用virtual还是用dynamic。不过,dynamic和virtual的区别可能对于编写application framework的程序员或者对那些效率问题至关重要的程序来讲才比较重要,对于一般的应用,虚拟方法不会很多,程序规模也不是很大的情况,一般用virtual就够了。

Object Pascal也支持abstract method,只要在函数声明中加上abstract关键字即可。当然了,只有virtual或者dynamic方法才能够声明为 abstract。只是和C++中不同,你可以建立abstract class的实例,并且调用它的abstract方法:

type

TTest=class

proceudre f:virtual;abstract;

end;

procedure TForm1.FormCreate(Sender:TObject);

var

t: TTest;

begin

t := TTest.Create;

t.f;

t.Free;

end;

尽管你会得到一个编译器警告Constructing instance of 'XXXX' containing abstract method 'XXXX.XX',但是程序仍然可以运行,只是当调用t.f的时候会产生一个运行时刻异常。不知道Object Pascal为什么这样安排,在C++中,构造一个含有抽象方法的对象无论如何都不会成功的。Object Pascal为什么要这样处理呢?我不知道。

你可能没有注意到一个关于abstract的小问题:下面的代码会有问题吗?

type

TTest=class

procedure f;virtual;abstract;

end;

TTest2=class(TTest)

procedure f;override;

end;

implementation

procedure TTest2.f;

begin

inherited;

ShowMessage(‘Test2.f!’);

end;

procedure TForm1.FormCreate(Sender:TObject);

var

t : TTest2;

begin

t := TTest2.Create;

t.f;

t.Free;

end;

在Delphi 5中,上面的代码会产生一个Abstract异常。关键在于inherited调用了基类的abstract方法。而在Delphi6中,编译器能够自动识别这种情况,从而不会导致问题。显然,Delphi 6中的这种增强更有利于OO的封装特性,你可以放心大胆的使用inherited,而不用担心基类的方法是否abstract。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有