C++ Class References

C++ Class References

本文关键字:References Class C++      更新时间:2023-10-16
来自

Delphi,我习惯于像这样使用类引用(元类(:

type
  TClass = class of TForm;
var
  x: TClass;
  f: TForm;
begin
  x := TForm;
  f := x.Create();
  f.ShowModal();
  f.Free;
end;

实际上,每个从 TObject 派生的类 X 都有一个名为 ClassType 的方法,它返回一个可用于创建 X 实例的 TClass。

C++有这样的事情吗?

元类在C++中不存在。 部分原因是因为元类需要虚拟构造函数和大多数派生到基础的创建顺序,这是C++没有的两件事,但 Delphi 有。

但是,特别是在C++Builder中,对Delphi元类的支持有限。 C++编译器具有__classid()__typeinfo()扩展,用于检索从TObject派生的任何类的Delphi兼容TMetaClass*指针。 该指针可以按原样传递给 Delphi 代码(您可以在 C++Builder 项目中使用 Delphi .pas 文件(。

TApplication::CreateForm() 方法在 Delphi 中实现,并在 C++ 中有一个 TMetaClass* 参数(尽管它的名字,它实际上可以实例化任何派生自 TComponent 的类,如果你不介意将TApplication对象分配为 Owner(,例如:

TForm *f;
Application->CreateForm(__classid(TForm), &f);
f->ShowModal();
delete f;

或者,如果您需要对构造函数调用进行更多控制,可以编写自己的自定义 Delphi 代码:

unit CreateAFormUnit;
interface
uses
  Classes, Forms;
function CreateAForm(AClass: TFormClass; AOwner: TComponent): TForm;
implementation 
function CreateAForm(AClass: TFormClass; AOwner: TComponent): TForm;
begin
  Result := AClass.Create(AOwner);
end;
end.

#include "CreateAFormUnit.hpp"
TForm *f = CreateAForm(__classid(TForm), SomeOwner);
f->ShowModal();
delete f;

显然,现代Delphi支持元类的方式与原始Smalltalk大致相同。

C++没有这样的事情。

在C++中模拟该功能的一个主要问题是,在运行时动态分配表示类型的值,并能够从这些值创建实例,C++必须静态地知道类型的构造函数才能实例化。

也许你可以通过使用静态多态性(包括函数重载和模板机制(来实现大部分相同的高级目标,而不是使用元类C++极端运行时多态性

但是,使用C++模拟效果的一种方法是使用可克隆的示例对象和/或几乎相同的想法,多态对象工厂对象。前者很不寻常,后者可以时不时地遇到(大多数区别在于参数化发生的位置:对于 examplar-object,它是该对象的状态,而在对象工厂中,它是创建函数的参数(。就我个人而言,我会远离它,因为C++是为静态类型设计的,这个想法是关于哄骗C++模仿具有非常不同特征和编程风格的语言等。

类型信息在运行时不存在C++。(除非启用RTTI,但它仍然与您需要的不同(

一个常见的习语是创建一个虚拟clone()方法,该方法显然克隆通常处于某种原型状态的对象。它类似于构造函数,但具体类型在运行时解析。

class Object
{
public:
    virtual Object* clone() const = 0;
};

如果你不介意花一些时间检查外国资源,你可以看看一个项目是如何做到的:https://github.com/rheit/zdoom/blob/master/src/dobjtype.h(注意:这是一个相当大的、不断发展的《毁灭战士》源端口,所以请注意,即使只是阅读也需要相当长的时间(。查看 PClass 和相关类型。我不知道这里到底做了什么,但根据我有限的知识,他们为每个类构建了一个具有必要元表的结构,并以可读性(或其他东西(的形式使用了一些预处理器魔法。他们的方法允许无缝创建通常的C++类,但增加了对PClass::FindClass("SomeClass"(的支持,以获取类引用并根据需要使用它,例如创建类的实例。它还可以检查继承,动态创建新类并用其他类替换类,即你可以用CWorksEverywhere替换CDoesntWorksUnderWinXP(例如,他们当然以不同的方式使用它(。我当时进行了快速研究,他们的方法并不例外,在某些网站上进行了解释,但由于我只有这么多兴趣,我不记得细节了。