来自Delphi,我习惯使用类引用(元类):
type
TClass = class of TForm;
var
x: TClass;
f: TForm;
begin
x := TForm;
f := x.Create();
f.ShowModal();
f.Free;
end;
实际上,从TObject派生的每个类都有一个名为ClassType的方法,它返回一个可用于创建X实例的TClass。
C ++中有类似内容吗?
答案 0 :(得分:3)
运行时使用C ++不存在类型信息。 (除非启用RTTI,但它仍然与您需要的不同)
一个常见的习惯用法是创建一个虚拟clone()
方法,该方法显然克隆了通常处于某种原型状态的对象。它类似于构造函数,但具体类型在运行时解析。
class Object
{
public:
virtual Object* clone() const = 0;
};
答案 1 :(得分:3)
显然,现代Delphi支持元类的方式与原始Smalltalk非常相似。
在C ++中没有类似的东西。
在C ++中模拟该功能的一个主要问题是,运行时动态分配表示类型的值,并且能够从这些值创建实例,在C ++中,必须静态地知道类型的构造函数。为了实例化。
通过使用C ++ 静态多态,包括函数重载和模板机制,而不是极端运行时多态,您可以实现大致相同的高级目标元类。
但是,使用C ++模拟效果的一种方法是使用 cloneable examples-objects ,和/或几乎相同的想法,多态对象工厂对象。前者非常不寻常,后者可以偶尔遇到(主要是差异在于参数化发生的地方:examplar-object是对象的状态,而对象工厂则是创建函数的参数)。我个人会远离那个,因为C ++是为静态类型而设计的,这个想法是关于将C ++哄骗模仿一种具有不同特征和编程风格的语言等。
答案 2 :(得分:2)
C ++中不存在元类。部分原因是因为元类需要虚拟构造函数和大多数派生到基础的创建顺序,这是C ++没有的两件事,但Delphi确实如此。
但是,特别是在C ++ Builder中,对Delphi元类有有限的支持。 C ++编译器具有__classid()
和__typeinfo()
扩展,用于从TMetaClass*
派生的任何类检索与Delphi兼容的TObject
指针。该指针可以按原样传递给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;
答案 3 :(得分:0)
如果你不介意花一些时间来检查外国资源,你可以看看项目是如何做到的:https://github.com/rheit/zdoom/blob/master/src/dobjtype.h(注意:这是一个相当大且不断发展的Doom源端口,所以建议即使只是阅读将需要相当长的时间)。看看PClass和相关类型。我不知道这里做了什么,但是从我有限的知识来看,他们为每个类构建了一个具有必要元数据的结构,并使用一些预处理器魔法以定义的形式提供可读性(或其他东西)。他们的方法允许无缝地创建通常的C ++类,但添加了对PClass :: FindClass(" SomeClass")的支持以获取类引用并根据需要使用它,例如创建类的实例。它还可以检查继承,动态创建新类并替换其他类,i。即你可以用CWorksEverywhere替换CDoesntWorksUnderWinXP(作为一个例子,他们当然会以不同的方式使用它)。那时我做了一个快速的研究,他们的方法并不特别,有些网站上有解释,但由于我只有很多兴趣,所以我不记得细节。