Question

Coming from Delphi, I'm used to using class references (metaclasses) like this:

type
  TClass = class of TForm;
var
  x: TClass;
  f: TForm;
begin
  x := TForm;
  f := x.Create();
  f.ShowModal();
  f.Free;
end;

Actually, every class X derived from TObject have a method called ClassType that returns a TClass that can be used to create instances of X.

Is there anything like that in C++?

Was it helpful?

Solution 2

Apparently modern Delphi supports metaclasses in much the same way as original Smalltalk.

There is nothing like that in C++.

One main problem with emulating that feature in C++, having run-time dynamic assignment of values that represent type, and being able to create instances from such values, is that in C++ it's necessary to statically know the constructors of a type in order to instantiate.

Probably you can achieve much of the same high-level goal by using C++ static polymorphism, which includes function overloading and the template mechanism, instead of extreme runtime polymorphism with metaclasses.

However, one way to emulate the effect with C++, is to use cloneable exemplar-objects, and/or almost the same idea, polymorphic object factory objects. The former is quite unusual, the latter can be encountered now and then (mostly the difference is where the parameterization occurs: with the examplar-object it's that object's state, while with the object factory it's arguments to the creation function). Personally I would stay away from that, because C++ is designed for static typing, and this idea is about cajoling C++ into emulating a language with very different characteristics and programming style etc.

OTHER TIPS

Metaclasses do not exist in C++. Part of why is because metaclasses require virtual constructors and most-derived-to-base creation order, which are two things C++ does not have, but Delphi does.

However, in C++Builder specifically, there is limited support for Delphi metaclasses. The C++ compiler has a __classid() and __typeinfo() extension for retrieving a Delphi-compatible TMetaClass* pointer for any class derived from TObject. That pointer can be passed as-is to Delphi code (you can use Delphi .pas files in a C++Builder project).

The TApplication::CreateForm() method is implemented in Delphi and has a TMetaClass* parameter in C++ (despite its name, it can actually instantiate any class that derives from TComponent, if you do not mind the TApplication object being assigned as the Owner), for example:

TForm *f;
Application->CreateForm(__classid(TForm), &f);
f->ShowModal();
delete f;

Or you can write your own custom Delphi code if you need more control over the constructor call:

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;

Type information does not exist at runtime with C++. (Except when enabling RTTI but it is still different than what you need)

A common idiom is to create a virtual clone() method that obviously clones the object which is usually in some prototypical state. It is similar to a constructor, but the concrete type is resolved at runtime.

class Object
{
public:
    virtual Object* clone() const = 0;
};

If you don't mind spending some time examining foreign sources, you can take a look at how a project does it: https://github.com/rheit/zdoom/blob/master/src/dobjtype.h (note: this is a quite big and evolving source port of Doom, so be advised even just reading will take quite some time). Look at PClass and related types. I don't know what is done here exactly, but from my limited knowledge they construct a structure with necessary metatable for each class and use some preprocessor magic in form of defines for readability (or something else). Their approach allows seamlessly create usual C++ classes, but adds support for PClass::FindClass("SomeClass") to get the class reference and use that as needed, for example to create an instance of the class. It also can check inheritance, create new classes on the fly and replace classes by others, i. e. you can replace CDoesntWorksUnderWinXP by CWorksEverywhere (as an example, they use it differently of course). I had a quick research back then, their approach isn't exceptional, it was explained on some sites but since I had only so much interest I don't remember details.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top