在delphi中名为create的函数的问题

时间:2010-12-15 00:46:47

标签: delphi delphi-2007

我有一个像这样声明的基类

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

提前致谢。

4 个答案:

答案 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);之前清除dlxor 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