1

私はしばらく C++ を使用してきましたが、C++ でこの Delphi Factory 構成を行う方法をまだ理解できていないことが、時々私を悩ませています。

私が理解できない重要な部分は、C++ でクラス型への参照を渡す方法です。Delphi には「TClass」型があります。このタイプの変数は、何らかのクラスへの参照です。class of MyClass新しいクラス参照型を定義する構文を使用して、クラス参照が参照できるクラスを制限できます。

「Delphi クラス リファレンス」という用語 =/= 「クラスの C++ インスタンス」という用語に注意してください。

Pascal に慣れていない人のために説明すると、変数はvariable: typeC スタイルではなく宣言されていtype variableます。同様に、関数の戻り値の型は、パラメーター リストと名前の後に表示されます。

次の例の構文は、ボイラープレート的でないように簡略化したものです。Delphi 開発者には、ひどい書式設定をしてしまったことをお詫びします。重要な部分はコメントで説明されています。

program demo;

{$APPTYPE CONSOLE}

// declarations

type

  Base = class
  public constructor Create(name: string); virtual;
  end;

  // Class reference which refers to Base and its descendants
  BaseClass = class of Base;

  ChildA = class(Base)
  public constructor Create(name: string); override;
  end;

  ChildB = class(Base)
  public constructor Create(name: string); override;
  end;

// implementation

constructor Base.Create(name: string);
begin
  WriteLn('Base says hi to ' + name);
end;

constructor ChildA.Create(name: string);
begin
  inherited Create(name);
  WriteLn('ChildA says hi to ' + name);
end;

constructor ChildB.Create(name: string);
begin
  WriteLn('ChildB says hi to ' + name);
end;

// *** THIS IS THE BIT THAT I'M INTERESTED IN ***
// The function doesn't know at compile time exactly what class it is being
// asked to construct.  The compiler knows that it is or inherits from Base.
// I can't find any kind of "class reference" in C++.
function ConstructSomething(ClassType: BaseClass; name: string): Base;
begin
  Result := ClassType.Create(name);
end;

// Equivalent to "main()" in C
begin

  // Pass references to a class to the ConstructSomething function
  ConstructSomething(Base, 'Mark');
  WriteLn('');

  ConstructSomething(ChildA, 'Mark');
  WriteLn('');

  ConstructSomething(ChildB, 'Mark');
  WriteLn('');

end.

出力:

Base says hi to Mark

Base says hi to Mark
ChildA says hi to Mark

ChildB says hi to Mark

子クラスへの参照が渡されると、子クラスが作成されることに注意してください。このデモでは、ChildB で基本コンストラクターを呼び出さないのは、"クラス参照" の概念をもう少し明確にするためです。

4

2 に答える 2

1

C++ には、Delphi のクラス参照のようなものは組み込まれていません。また、クラス参照は単なる仮想コンストラクタ以上のものです。非常に便利な (仮想および非仮想) クラス メソッドを定義することもできます。

C++ テンプレートを使用してクラス参照を模倣できますが、定型コードがいくつか付属しており、クラスとメタクラスに個別のクラスを定義する必要があります。言うまでもなく、これは C++ を行うためのかなり一義的な方法です。

// some central header

template <typename Base>
  class Metaclass;


// your header

class Base
{
public:
  Base (const String& name) { /*...*/ }
};
template<>
  class Metaclass<Base>
{
public:
  virtual Base* create (const String& name);
};
extern Metaclass<Base> classof_Base;

class ChildA : public Base
{
public:
  ChildA (const String& name) { /*...*/ }
};
template<>
  class Metaclass<ChildA> : public Metaclass<Base>
{
public:
  // note how I'm making use of C++'s support for covariance
  ChildA* create (const String& name) override;
};
extern Metaclass<ChildA> classof_ChildA;

class ChildB : public MyBase
{
public:
  ChildB (const String& name) { /*...*/ }
};
template<>
  class Metaclass<ChildB> : public Metaclass<Base>
{
public:
  ChildB* create (const String& name) override;
};
extern Metaclass<ChildB> classof_ChildB;


// your source file

Metaclass<Base> classof_Base;
Base* Metaclass<Base>::create (const String& name)
{
  return new Base (name);
}

Metaclass<ChildA> classof_ChildA;
MyBase* Metaclass<ChildA>::create (const String& name)
{
  return new ChildA (name);
}

Metaclass<ChildB> classof_ChildB;
MyBase* Metaclass<ChildB>::create (const String& name)
{
  return new ChildB (name);
}

Delphi コードを C++ で複製できるようになりました。

Base* constructSomething (Metaclass<Base>& classType, const String& name)
{
  return classType.create (name);
}

int main (void)
{
  constructSomething (classof_Base, "Mark");
  std::sprintf ("\n");
  constructSomething (classof_ChildA, "Mark");
  std::sprintf ("\n");
  constructSomething (classof_ChildB, "Mark");
  std::sprintf ("\n");
}
于 2014-08-15T20:38:21.193 に答える