如何将以下"class reference"机制从德尔福转换为C++11?

How would I translate the following "class reference" mechanism from Delphi to C++11?

本文关键字:德尔福 转换 C++11 机制 reference class      更新时间:2023-10-16

我已经使用c++有一段时间了,有一件事偶尔会让我感到困扰,那就是我还没能弄清楚如何在c++中实现这个Delphi Factory构造。

我不明白的关键部分是如何在c++中传递对类类型的引用。在Delphi中,我们有"TClass"类型。这种类型的变量是对某个类的引用。我们可以使用class of MyClass语法来定义一个新的类引用类型,从而限制类引用可以引用的类。

注意术语"Delphi类引用" =/= "类的c++实例"

对于那些不熟悉Pascal的人来说,变量声明为variable: type而不是c风格的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

注意,当传递对子类的引用时,将创建该子类。在本演示中,故意不调用childdb中的基构造函数,以使"类引用"的概念更加明显。

最接近的方法是使用模板函数

template<typename ClassType>
Base* ConstructSomething(string name)
{
   return new ClassType(name);
}
int main()
{
    ConstructSomething<Base>("Mark");
    ConstructSomething<ChildA>("Mark");
}

ClassType不能在运行时选择-必须在编译时知道

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);
}

现在您可以在c++中复制Delphi代码:

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");
}