我有一个像这样声明的基类
type
TBaseClass=class
protected
constructor Create(LoadData:boolean;const Param1,Param2:string); overload;
public
Destructor Destroy; override;
end;
现在在另一个单元中,从TChid_Class
TBaseClass
TChid_Class=class(TBaseClass)
function Create(const Param1, Param2 : String;const Param3 : OleVariant ; var Param4 : LongInt): Integer;overload;
constructor Create; overload;
constructor Create(LoadData:boolean); overload;
end;
在这个类中存在一个名为Create
的函数,就像构造函数一样,问题是,当我尝试为TChid_Class
创建一个实例时,我有一个访问冲突。
我写了这个显示问题的小型控制台应用程序
program TestClass;
{$APPTYPE CONSOLE}
uses
Variants,
SysUtils;
type
TBaseClass=class
protected
constructor Create(LoadData:boolean;const Param1,Param2:string); overload;
public
Destructor Destroy; override;
end;
TChid_Class=class(TBaseClass)
function Create(const Param1, Param2 : String;const Param3 : OleVariant ; var Param4 : LongInt): Integer;overload;
constructor Create; overload;
constructor Create(LoadData:boolean); overload;
end;
{ TBaseClass }
constructor TBaseClass.Create(LoadData: boolean; const Param1, Param2: string);
begin
inherited Create;
Writeln('constructor TBaseClass.Create(LoadData: boolean; const Param1, Param2: string);');
end;
destructor TBaseClass.Destroy;
begin
//Code
inherited;
end;
{ TChid_Class }
function TChid_Class.Create(const Param1, Param2: String; const Param3: OleVariant; var Param4: Integer): Integer;
begin
Writeln('function create');
Result:=0;
end;
constructor TChid_Class.Create;
begin
Writeln('constructor TChid_Class.Create');
Create(True);
end;
constructor TChid_Class.Create(LoadData: boolean);
begin
Writeln('constructor TChid_Class.Create(LoadData: boolean)'); //here is the access violation
Create(LoadData,'Value 1','Value 2');
end;
var
Invoker : TChid_Class;
Pid : integer;
begin
try
Invoker:=TChid_Class.Create;
try
Invoker.Create('','',Unassigned,Pid)
finally
Invoker.Free;
end;
except
on E:Exception do
Writeln(E.Classname, ': ', E.Message);
end;
readln;
end.
如果我重命名函数create,问题就会消失,但我正在寻找一个没有重命名创建函数或构造函数的解决方案。
使用delphi 2007
提前致谢。
答案 0 :(得分:4)
使用Delphi 7我也得到了一个AV。重命名方法或移动它(按照Sertac Akyuz的建议)修复AV。
通过查看汇编程序我发现了什么:
在创建新对象时,在调用构造函数之前,将非零值放在寄存器dl
中。
mov dl,$01 // dl set to 1
mov eax,[$00401268]
call TChild_Class.Create
然后在构造函数中,在begin
行上,当dl
非零时调用ClassCreate。
test dl,dl
jz +$08 //if dl = 0 then do not call ClassCreate
add esp,-$10
call -$00000396 //calls ClassCreate
但是当你的代码出错时,编译器会在调用dl
之前再次将Create(True)
设置为1,所以在begin
的{{1}}行上,ClassCreate是再次调用导致AV。
重命名函数或移动声明后,编译器会在调用TChid_Class.Create(LoadData: boolean);
之前清除dl
(xor edx,edx
)而不是将其设置为1。
我的猜测是它是Delphi编译器中的一个错误,它在Delphi 2010及更高版本中得到修复。
答案 1 :(得分:2)
部分答案:在您的构造函数TChid_Class.Create(LoadData:boolean)中,您在Create调用中缺少'inherited'。如果在演示项目中调用* TChid_Class.Create(True)*,这将修复示例代码中的AV。
constructor TChid_Class.Create(LoadData: boolean);
begin
Writeln('constructor TChid_Class.Create(LoadData: boolean)'); //here is the access violation
inherited Create(LoadData,'Value 1','Value 2'); //add "INHERITED"
end;
答案 2 :(得分:1)
您使用错误的方式创建对象!您无法在创建时在一个类中调用多个构造函数,但您可以仅继承创建。 所以正确的方法是:
constructor TChid_Class.Create(LoadData: boolean = True);
begin
Writeln('constructor TChid_Class.Create(LoadData: boolean)'); //here is the access violation
inherited Create(LoadData,'Value 1','Value 2');
end;
保留字继承告诉父构造函数该对象是在子类构造函数中创建的。 在D2007下检查!
答案 3 :(得分:0)
在Delphi 2007的最新更新之前,这是一个编译器错误 它适用于Delphi 2009及以上版本。
将Create
功能重命名为Initialize
可以解决您的问题。它不仅是一种解决方法,
但是对于修复错误和从编码角度来看都是正确的:
作为一般规则,对象实例的构造和初始化应该有明显的区别。
- 的Jeroen