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:

template 
class 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::ClassRef ClassRefType;                                   
  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::ClassRef ClassRefType;                          
  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.




   english english

 
Letzte Neuigkeiten
15.11.19
DelphiXE2Cpp11 Klassenreferenzen [mehr...]

16.10.19
Delphi2C# beta Angebot [mehr...]