Other compiler ClassRef

Top  Previous  Next

What is translated > class-reference type > Other compiler ClassRef

As for C++Builder where a classTMetaClass is defined, for other compilers such a class is defined too in the code delivered with Delphi2Cpp. In addition the type TClass is defined as a pointer to TMetaClass:

 

typedef TMetaClass* TClass

 

TMetaClass is the class reference type for TObject and it is the base class of all class reference types of all other classes. These class references are defined as instances of a class ClassRef, which is a generic class:

 

template <typename Class>

class ClassRef

 

where the template parameter denotes the original class. That way for a hierarchy of classes, which are derived one from another, there is a parallel hierarchy of class references. The class references are implemented as singletons and only created, if needed. To avoid unwanted side effects at the creation of these classes the variable _CreatingClassInstance can be used. The exact definition of the ClassRef class is tricky and works only, because Delphi2Cpp also inserts some additional helper code into every class declaration. The following code demonstrates how a small class factory using class references is converted from Delphi to C++:

 

 

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(TDerived);                   

 result := p.GetName = 'TDerived';      

end;                                     

 

 

->

 

 

class TBase : public System::TObject                                                                  

{                                                                                                                                                                                   

public:                                                                                                

  typedef System::ClassRef<TBase> ClassRefType;  

  ClassRefType* ClassType() const {return  System::class_id<TBase>();}

  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<TDerived> ClassRefType;  

  ClassRefType* ClassType() const {return  System::class_id<TDerived>();}

  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<TDerived>());            

  result = P->GetName() == L"TDerived";                                

  return result;                                                         

}                                                                        

 

 

The central point in this code is the call of the class_id-function:

 

P = make(class_id<TDerived>());

 

The class_id-function fulfills the same purpose as the __classid-function in C++Builder code: it delivers class references. In the example the class_id-function delivers the class reference to the class TDerived.

 

 

If TDerived wouldn't have a standard constructor, instead of the line

 

static TDerived* Create() {return new TDerived();}

 

the line

 

static TDerived* Create() {ThrowNoDefaultConstructorError(ClassName()); return nullptr}

 

would have been written. If TDerived were an abstract class, the line would have been:

 

static TDerived* Create() {ThrowAbstractError(ClassName()); return nullptr}

 

 

Other uses of Delphi class references are reproduced in C++ too. For example:

 

  ClassRef := Sender.ClassType;

 

  while ClassRef <> NIL do

  begin

    s := ClassRef.ClassName);

    ClassRef := ClassRef.ClassParent;

  end;

 

is converted to:

 

TClass ClassRef = Sender->ClassType();

  

while(ClassRef != nullptr)

{

  s = ClassRef->ClassName();

  ClassRef = ClassRef->ClassParent();

}

 

However only a minimal frame for class reference manipulations is created and there have to be standard constructors for all classes with used class references.

 

 

 



This page belongs to the Delphi2Cpp Documentation

Delphi2Cpp home  Content