李维的inside vcl的确有一些bug,希望大家提出方便讨论~

del_c_sharp 2004-02-15 12:50:41
李维的inside vcl的确有一些bug,希望大家提出方便讨论,并注明页码

贴 reallike 发现的几个问题:

问题一:

书中的论述是这样的:
{ ======================================================== }
让我们看一个范例,在下面的程序代码中声明了如下的TBase类:
TBase = class(TObject)
private
{ Private declarations }
iRef : Integer;
...
end;
要建立TBase对象时除了可使用下面的建构函数:
aBObj := TBase.Create;
我们也可以使用如下的程序代码:
var
aBObj : TBase;
aObj : TObject;
begin
...
try
aObj := TObject(TBase.NewInstance);
aBObj := TBase(aObj.Create);
// 上面一句可能存在问题。
// 按照这种写法,调用的是 TObject.Create 而不是 TBase.Create。
// 那么这种写法和 aBObj := TBase.Create; 是不等价的。
//
// 举个例子,假设 TBase.Create 函数体内有一条赋值语句 iRef := 100;
// 当我们使用通常的对象创建方法,即 aBObj := TBase.Create;
// 此时,当对象构造完毕时 aBObj.iRef 是等于 100 的。
// 但如果按照现在的写法,aBObj.iRef 仍然为 0。
// 但如果这个语句改成 aBObj := TBase(aObj).Create; 就不会有问题。
//
// 李维在这里举了一个 TApplication.CreateForm 的例子来验证他的说法。
// 但有一点他没有注意到 TComponent 的构造函数 Create 是 virtual 的。
// 而 TObject.Create 却不是 virtual 的。
...
finally
FreeAndNil(aBObj);
end;
end;
问题二:

书中的论述是这样的:
{ ======================================================== }
因此我们可以推知 MethdodName 似乎只会对从 TComponent 继承下来的类的 published 方法才有作用。
//
// 李维得出这个结论是来源于下面的这个例子
//
procedure TForm1.Button7Click(Sender: TObject);
var
aObj : TDerived;
sData : String;
aPtr : Pointer;
begin
sData := 'TDerived at ' + DateTimeToStr(Now);
aObj := TDerived.Create(sData, HashOf(sData));1
...
ShowMethodAddress(aObj, 'MyMethod1');
aPtr := ShowMethodAddress(aObj, 'MyMethod2');
sData := MethodName(aPtr);
// 由于此处运行的结果是 sData = ''; 也就是没能获得相应的 MethodName
// 因此,李维得出了上述结论。
// 但是我认为这个结论是错的。因为这个语句有问题。
//
// sData := MethodName(aPtr); 实际上调用的是 TForm1.MethodName 函数
// MyMethod2 根本不是 TForm1 的成员函数,当然获取不了 MethodName。
//
// 如果该语句改成 sData := TDerived.MethodName(aPtr);
// 或者改成 sData := aObj.MethodName(aPtr);
// 都能够获得正确的 MethodName。
//
// 因此,MethdodName 对从 TObject 继承下来的类的published方法都有作用。
// 李维的结论是不对的。

sData := Format('%x : %s', [Integer(aPtr), sData]);
Memo1.Lines.Add(sData);
...
end;
{ ======================================================== }


问题三:

书中的论述是这样的:
{ ======================================================== }
现在让进行一个实验,看看VMT表格建立的时机。
procedure TForm1.Button4Click(Sender: TObject);
var
aPnl : TPanel;
begin
aClass := aPnl.ClassType;
sClassName := 'TPanel';
ShowVMTContent(aClass);
aPnl := TPanel.Create(Self);
aClass := aPnl.ClassType;
sClassName := 'TPanel';
ShowVMTContent(aClass);
FreeAndNil(aPnl);
end;
上面的程序代码首先声明了一个区域 TPanel 变量 aPnl,接着在还未实际建立 TPanel 对象之前我们藉由 aPnl 显示 VMT 的内容,得到的结果应该是无意义的内容。然而一旦当 TPanel 对象实际在内存中建立之后就可以取得 TPanel 的 VMT 中的内容。我们应该可以推知 VMT 应该是在第一个类对象被建立时才会建立完整的 VMT 内容。

// 我个人认为,李维的这个结论也是错误的。
// 因为当还未实际建立 TPanel 对象时,aPnl 并没有指向一个实际的 TPanel 对象,因此 aPnl 更不可能跟 TPanel 的 VMT 有关联。但是这并不能证明 TPanel 的 VMT 就没有建立。实际上,我们可以在没有建立任何 TPanel 对象时,调用 TPanel.ClassName,而且该函数能够返回正确的值 'TPanel',而 ClassName 就是从 VMT 中获得的。我想这也能够说明,在第一个类对象被建立时,VMT 已经建立起来了。


很钦佩reallike的细致。。。。。。。
...全文
46 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复

5,390

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧