D
ddev
Unregistered / Unconfirmed
GUEST, unregistred user!
虽然 Borland 号称 BCB 能够很好地兼容 Pascal,而将 VCL 作为
BCB 的一块很重要的基石,但是,这些时期以来,通过对 VCL
多方位的应用,发现:对于 BCB,VCL 并没有在纯 Pascal/Delphi
环境中的那种稳定性!而且是问题多多,太多,且要么没有问题,
要么就是很严重的问题。
分析一下,这与 C++/Object Pascal 类的构造有着密切的关系。
大家都知道,C 类是从上向下构造,而 Pascal 刚好相反;
看下面一段代码:
type
TMyEdit = class(TEdit)
public
constructor Create(AOwner: TComponent);
override;
end;
constructor TMyEdit.Create(AOwner: TComponent);
begin
//什么都不作,也不继承
//inherited Create(AOwner);
end;
var
MyEdit: TMyEdit = nil;
procedure TForm1.Button1Click(Sender: TObject);
begin
MyEdit := TMyEdit.Create(Application);
=> MyEdit.Parent := Self;
MyEdit.Left := 20;
MyEdit.Top := 16;
MyEdit.Visible := True;
end;
注意到吗,在我标出那一断点,出现异常。这个异常是
正确的,因为 Pascal 是从下向上构造。子类没有“完
整”地构造自己或没有指定继承,那么子类的其他类属
性也不会得到很好的初始化,因此该类的实例化将失败!
而对于标准的 C 类构造,同样考虑这段代码,应该发现:
该类能够正常实例化!
class TMyEdit : public TEdit
{
public:
__fastcall TMyEdit(TComponent* AOwner);
};
__fastcall TMyEdit::TMyEdit(TComponent* Owner) : TEdit(Owner)
{
};
TMyEdit* MyEdit = NULL;
void __fastcall TForm1::Button1Click(TObject *Sender)
{
MyEdit = new TMyEdit(Application);
MyEdit->Parent = this;
MyEdit->Left = 20;
MyEdit->Top = 16;
}
这说明什么?=> 一个 C 类的继承(构造)是强制的,在它的构
造中必须先构造父类,然后才是子类,因此可以说:C 类的构
造是一个类群的构造;而在 Pascal 中,当你构造子类时,必
须明确一个类的构造次序!这样,在一个 Delphi 应用中,一
个类的宿主是很明确的,因为这在子类中必须声明;而在一个
C 类中,问题并不是那么简单,因为父类如果构造了宿主,那
么子类宿主的改变,将不会“反映”到它的父类,原因很简单:
主类已经构造完毕!错误将由此而来。
当然,Borland 已经有办法解决这个问题,并且在大部分情况下,
能够正常运行,但在某些特殊的构造中,如:在 DLL 中用 Delphi
写的 VCL 类件,如果调用时需要 VCL 的一些 RTTI 信息,如:
宿主,那么问题就来了,在 DLL 及应用均为调试状态时,一般地,
BCB 会核选 Stack Frames,以保持与 VCL 的通讯;而在发布状态
时,却清除的 Stack Frames 并作出了其他的某些变动,致使应用
中的 VCL 与 DLL 中的 VCL 在通讯时会产生严重异常!
原因我也不清楚,但我的一个程序确确实实发生了这种情况。
莫明所以,因此贴出这个想法,想请各位高手指正,希望不吝指教。
BCB 的一块很重要的基石,但是,这些时期以来,通过对 VCL
多方位的应用,发现:对于 BCB,VCL 并没有在纯 Pascal/Delphi
环境中的那种稳定性!而且是问题多多,太多,且要么没有问题,
要么就是很严重的问题。
分析一下,这与 C++/Object Pascal 类的构造有着密切的关系。
大家都知道,C 类是从上向下构造,而 Pascal 刚好相反;
看下面一段代码:
type
TMyEdit = class(TEdit)
public
constructor Create(AOwner: TComponent);
override;
end;
constructor TMyEdit.Create(AOwner: TComponent);
begin
//什么都不作,也不继承
//inherited Create(AOwner);
end;
var
MyEdit: TMyEdit = nil;
procedure TForm1.Button1Click(Sender: TObject);
begin
MyEdit := TMyEdit.Create(Application);
=> MyEdit.Parent := Self;
MyEdit.Left := 20;
MyEdit.Top := 16;
MyEdit.Visible := True;
end;
注意到吗,在我标出那一断点,出现异常。这个异常是
正确的,因为 Pascal 是从下向上构造。子类没有“完
整”地构造自己或没有指定继承,那么子类的其他类属
性也不会得到很好的初始化,因此该类的实例化将失败!
而对于标准的 C 类构造,同样考虑这段代码,应该发现:
该类能够正常实例化!
class TMyEdit : public TEdit
{
public:
__fastcall TMyEdit(TComponent* AOwner);
};
__fastcall TMyEdit::TMyEdit(TComponent* Owner) : TEdit(Owner)
{
};
TMyEdit* MyEdit = NULL;
void __fastcall TForm1::Button1Click(TObject *Sender)
{
MyEdit = new TMyEdit(Application);
MyEdit->Parent = this;
MyEdit->Left = 20;
MyEdit->Top = 16;
}
这说明什么?=> 一个 C 类的继承(构造)是强制的,在它的构
造中必须先构造父类,然后才是子类,因此可以说:C 类的构
造是一个类群的构造;而在 Pascal 中,当你构造子类时,必
须明确一个类的构造次序!这样,在一个 Delphi 应用中,一
个类的宿主是很明确的,因为这在子类中必须声明;而在一个
C 类中,问题并不是那么简单,因为父类如果构造了宿主,那
么子类宿主的改变,将不会“反映”到它的父类,原因很简单:
主类已经构造完毕!错误将由此而来。
当然,Borland 已经有办法解决这个问题,并且在大部分情况下,
能够正常运行,但在某些特殊的构造中,如:在 DLL 中用 Delphi
写的 VCL 类件,如果调用时需要 VCL 的一些 RTTI 信息,如:
宿主,那么问题就来了,在 DLL 及应用均为调试状态时,一般地,
BCB 会核选 Stack Frames,以保持与 VCL 的通讯;而在发布状态
时,却清除的 Stack Frames 并作出了其他的某些变动,致使应用
中的 VCL 与 DLL 中的 VCL 在通讯时会产生严重异常!
原因我也不清楚,但我的一个程序确确实实发生了这种情况。
莫明所以,因此贴出这个想法,想请各位高手指正,希望不吝指教。