7

基本クラスでクラスコンストラクターを定義する場合(つまり、静的クラス変数を設定する場合)、派生クラスでこのクラスコンストラクターをオーバーライドし、継承された階層の親からコンストラクターを呼び出すことは可能ですか?

例:

TBaseclass = class(TObject)
public
   class constructor ClassCreate; virtual;
end;

TOtherClass = class(TBaseClass)
public
  class constructor ClassCreate; override;
end;

**implementation**

class constructor TBaseClass.ClassCreate;
begin
  //do some baseclass stuff
end;

class constructor TotherClass.ClassCreate;
begin
  inherited;
  //do some other stuff
end;
4

2 に答える 2

17

クラスコンストラクターは多態的に呼び出すことができないため、仮想である理由はありません。それらを直接呼び出すことはできません。コンパイラは、プログラムで使用されているクラスに基づいて、それらへの呼び出しを自動的に挿入します。仮想メソッドは実行時のポリモーフィズム用ですが、コンパイラーはコンパイル時に呼び出すクラスコンストラクターを正確に認識しているため、クラスコンストラクターまたはデストラクタを動的にディスパッチする必要はありません。

inheritedただし、継承には仮想メソッドは必要ないため、クラスコンストラクタまたはクラスデストラクタでの使用に問題はありません。ただし、 Davidの回答が指摘しているように、クラスを複数回初期化することは一般的に賢明ではないため、コンパイラーはへの呼び出しを無視します。inheritedこれは、継承されたクラスコンストラクターを実際に呼び出すことができた場合に行うことです。2回発生する必要があることがある場合は、それを発生させるための別の方法を見つける必要があります。

于 2012-06-18T14:38:54.897 に答える
10

まず、クラスコンストラクターを仮想化することはできないため(仮想化することは意味がありません)、コードをコンパイルするには、キーワードvirtualとキーワードを削除する必要があります。override

クラスコンストラクターは通常、クラス変数を初期化するために使用されます。クラス変数は通常、一度だけ初期化する必要があります。inherited質問で提案した方法で呼び出すことができればTBaseClass.ClassCreate、実際には1回だけ呼び出す必要があるのに、複数回呼び出されることになります。

クラスコンストラクターで記述できinherited、コードはコンパイルされますが、コンパイラーはそれを無視します。

program ClassConstructors;

{$APPTYPE CONSOLE}

uses
  SysUtils;

var
  Count: Integer;

type
  TBaseclass = class
  public
    class constructor ClassCreate;
  end;

  TOtherClass = class(TBaseClass)
  public
    class constructor ClassCreate;
  end;

class constructor TBaseClass.ClassCreate;
begin
  inc(Count);
end;

class constructor TotherClass.ClassCreate;
begin
  inherited;
end;

begin
  TBaseClass.Create.Free;
  TOtherClass.Create.Free;
  Writeln(Count);//outputs 1
  Readln;
end.

もちろん、両方のクラスコンストラクターが実行されることに注意してください。

于 2012-06-18T14:39:02.100 に答える