texttransformer.jpg

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();}
  TBase* Create() {return new TBase();}
  static TBase* SCreate() {return new TBase();}
  System::String ClassName() {return L"TBase";}
  static System::String SClassName() {return L"TBase";}
  TBase();                                                                                            
};                                                                                                     

typedef TBase::ClassRefType TBaseClass;                                                              

class TDerived : public TBase                                                                       
{                                                                                                                                                                                   
public:                                                                                                
  typedef System::ClassRef ClassRefType;  
  ClassRefType* ClassType() const {return  System::class_id();}
  TDerived* Create() {return new TDerived();}
  static TDerived* SCreate() {return new TDerived1();}
  System::String ClassName() {return L"TDerived";}
  static System::String SClassName() {return L"TDerived";}
  TDerived();                                                                                        
};                                                                                                     

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
29.01.24
Aurora2Cpp: Delphi 7 Konverter [more...]

19.10.23
Delphi2Cpp 2.3: Konvertierung von DFM-Dateien [more...]



[aus Fallstudie...]

"Eine Meisterleistung -- Delphi2Cpp hat alle meine Erwartungen weit übertroffen."


Tony Hürlimann
virtual-optima 29.08.2011



"Ich muss mich nochmal für deinen Einsatz und die Qualität deiner Arbeit bedanken, das ist absolut überdurchschnittlich ..."


Gerald Ebner


 
Diese Homepage ist aus einfachen Texten mit [Minimal Website ]generiert.

Minimal Website
Minimal Website ist mit Hilfe des TextTransformers hergestellt.

TextTransformer
Der TextTransformer ist gemacht mit dem Borland CBuilder

  borland