In Delphi können Klassenmethoden aufgerufen werden, ohne zunächst eine Instanz der Klasse zu erzeugen. Dies ist ähnlich wie der Aufruf statischer Methoden in C++. Aber in C++ ist es nicht möglich, wie in Delphi Klassen Variablen als Werte zuzuweisen und anschließend Instanzen der Klassen zu erzeugen, indem virtuelle Klassenmethoden dieser Variblen aufgerufen werden.
Für den C++Builder gibt es die __classid Funktion als spezielle Erweiterung, um solche Klassenreferenzen zu erhalten. Lediglich eine kleine Delphi Unit muss zu einem C++Builder Projekt hinzugefügt werden, um aus solchen Klassenreferenzen Instanzen der Klassen zu erzeugen.
Mit anderen Compilern das Gleiche zu erreichen ist sehr viel schwieriger.
So wie für den C++Builder die Klasse TMetaClass definiert ist, so wird sie auch für andere Compiler definiert. Außerdem wird der TClass Typ als Zeiger auf TMetaClass definiert:
typedef TMetaClass* TClass
TMetaClass ist der Klassenreferenztyp für TObject und ist die Basisklasse für alle Klassenreferenztypen aller anderen Klassen. Diese Klassenreferenzen sind definiert als Instanzen einer generischen ClassRef-Klasse:
templateclass ClassRef
wobei der Template-Parameter für die originale Klasse steht. Aus diese Weise gibt es für eine Hierarchie von Klassen, die voneinander abgeleitet sind, eine parallele Hierarchie von Klassenreferenzen. Die Klassenreferenzen sind als Singletons implementiert und werden nur erzeugt, wenn sie gebraucht werden. Die exakte Definition der ClassRef-Klasse ist trickreich und nur möglich, weil DelphiXE2Cpp11 zusätzlichen Hilfcode in jede Klassendeklaration schreibt.
Der folgende Code demonstriert, wie eine kleine Klassen-Factory unter Benutzung von Klassenreferenzen von Delphi nach C++ konvertiert wird.
type TBase = class public function GetName: String; virtual; end;
TBaseClass = class of TBase;
TDerived = class(TBase) public function GetName: String; override; end;
TDerivedClass = class of TDerived;
implementation
function make(Base: TBaseClass): TBase; begin result := Base.Create; end;
function testTactory: boolean; var s : String; p : TBase; begin p := make(TDerived1); result := p.GetName = 'TDerived1'; end;
->
class TBase : public System::TObject { public: typedef System::ClassRefClassRefType; ClassRefType* ClassType() const {return System::class_id ();} static TBase* Create() {return new TBase();} static System::String ClassName() {return L"TBase";} virtual System::String GetName(); TBase(); };
typedef TBase::ClassRefType TBaseClass;
class TDerived : public TBase { public: typedef System::ClassRefClassRefType; ClassRefType* ClassType() const {return System::class_id ();} static TDerived* Create() {return new TDerived();} static System::String ClassName() {return L"TDerived";} virtual System::String GetName(); TDerived1(); };
typedef TDerived::ClassRefType TDerivedClass;
TBase* make(TBaseClass* Base) { TBase* result = nullptr; result = Base->Create(); return result; }
bool testfactory() { bool result = false; String s; TBase* P = nullptr; P = make(class_id()); result = P->GetName() == L"TDerived"; return result; }
Der zentrale Punkt in diesem Code ist der Aufruf der class_id-Funktion:
P = make(class_id());
Die class_id-Funktion erfüllt den gleichen Zweck wie die __classid-Funktion im C++Builder Code: sie liefert die Klassenreferenzen, im Beispiel, die Klassenreferenz zum TDerived-Typ.