我可以在“继承创建”之前做一些初始化吗?
Can I do some initializations before `Inherited Create`?
我想创建并启动一个线程,全部使用一个命令行 TClientCopyThread.Create(...)
。为此,我必须使用 Suspended = False
创建线程,以便它可以立即 运行。我知道当我写一个新对象的 constructor
时,首先我必须调用 inherited Create
以便创建对象的实例,然后进行初始化。但是在这里,如果我调用 inherited
线程将在没有初始化参数的情况下启动。我尝试最后调用 inherited
,它似乎正常工作(我没有收到任何访问冲突),但我不确定这是否是巧合。
TClientCopyThread = class(TThread)
private
OwnGUID: String;
SrcPath, DestPath: String;
Files: TFileNames;
RemoveIt: Boolean;
protected
procedure Execute; override;
public
constructor Create(const GUID, ASrcPath, ADestPath: String;
const FileNames: TFileNames; RemoveSrc: Boolean);
end;
constructor TClientCopyThread.Create(const GUID, ASrcPath, ADestPath: String;
const FileNames: TFileNames; RemoveSrc: Boolean);
var I: Integer;
begin
SrcPath:= Copy(ASrcPath, 1, Length(ASrcPath));
DestPath:= Copy(ADestPath, 1, Length(ADestPath));
SetLength(Files, Length(FileNames));
for I:= 0 to High(Files) do
Files[I]:= Copy(FileNames[I], 1, Length(FileNames[I]));
RemoveIt:= RemoveSrc;
FreeOnTerminate:= True;
inherited Create;
end;
要回答您的具体问题 - 是的,您可以在派生构造函数期间的任何时候调用 inherited Create
。它不需要是第一条语句(与 inherited Destroy
相同,作为析构函数中的最后一条语句)。 class 对象的内存在调用 any 构造函数之前已经完全分配,因此在调用 class 之前初始化派生的 class 的成员是安全的=12=]构造函数。但是,当从派生构造函数访问基础 class 成员时,您应该先调用 inherited
构造函数初始化它们,然后再访问它们。
也就是说,您对 TThread
构造函数工作原理的理解完全错误。从Delphi 6开始,基础class TThread
构造函数总是以挂起模式创建底层OS线程,然后恢复TThread.AfterConstruction()
中的线程在 所有 构造函数完全退出后,如果 TThread
对象是用 CreateSuspended=False
构造的。因此,您声称使用 CreateSuspended=False
调用 inherited Create
将立即启动线程 运行 自 2001 年 Delphi 6 以来一直不正确被释放。底层 OS 线程将不会启动 运行 直到 在 您的 TClientCopyThread.Create()
构造函数退出后。因此,无论您如何设置 CreateSuspended
.
,您的 Execute()
方法将 永远不会 作用于未初始化的成员
您所描述的(成员初始化之前的线程 运行)是 Delphi 5 和更早版本中的 bug,已在 Delphi6.
我想创建并启动一个线程,全部使用一个命令行 TClientCopyThread.Create(...)
。为此,我必须使用 Suspended = False
创建线程,以便它可以立即 运行。我知道当我写一个新对象的 constructor
时,首先我必须调用 inherited Create
以便创建对象的实例,然后进行初始化。但是在这里,如果我调用 inherited
线程将在没有初始化参数的情况下启动。我尝试最后调用 inherited
,它似乎正常工作(我没有收到任何访问冲突),但我不确定这是否是巧合。
TClientCopyThread = class(TThread)
private
OwnGUID: String;
SrcPath, DestPath: String;
Files: TFileNames;
RemoveIt: Boolean;
protected
procedure Execute; override;
public
constructor Create(const GUID, ASrcPath, ADestPath: String;
const FileNames: TFileNames; RemoveSrc: Boolean);
end;
constructor TClientCopyThread.Create(const GUID, ASrcPath, ADestPath: String;
const FileNames: TFileNames; RemoveSrc: Boolean);
var I: Integer;
begin
SrcPath:= Copy(ASrcPath, 1, Length(ASrcPath));
DestPath:= Copy(ADestPath, 1, Length(ADestPath));
SetLength(Files, Length(FileNames));
for I:= 0 to High(Files) do
Files[I]:= Copy(FileNames[I], 1, Length(FileNames[I]));
RemoveIt:= RemoveSrc;
FreeOnTerminate:= True;
inherited Create;
end;
要回答您的具体问题 - 是的,您可以在派生构造函数期间的任何时候调用 inherited Create
。它不需要是第一条语句(与 inherited Destroy
相同,作为析构函数中的最后一条语句)。 class 对象的内存在调用 any 构造函数之前已经完全分配,因此在调用 class 之前初始化派生的 class 的成员是安全的=12=]构造函数。但是,当从派生构造函数访问基础 class 成员时,您应该先调用 inherited
构造函数初始化它们,然后再访问它们。
也就是说,您对 TThread
构造函数工作原理的理解完全错误。从Delphi 6开始,基础class TThread
构造函数总是以挂起模式创建底层OS线程,然后恢复TThread.AfterConstruction()
中的线程在 所有 构造函数完全退出后,如果 TThread
对象是用 CreateSuspended=False
构造的。因此,您声称使用 CreateSuspended=False
调用 inherited Create
将立即启动线程 运行 自 2001 年 Delphi 6 以来一直不正确被释放。底层 OS 线程将不会启动 运行 直到 在 您的 TClientCopyThread.Create()
构造函数退出后。因此,无论您如何设置 CreateSuspended
.
Execute()
方法将 永远不会 作用于未初始化的成员
您所描述的(成员初始化之前的线程 运行)是 Delphi 5 和更早版本中的 bug,已在 Delphi6.