I've used C++ for a while and one thing which occasionally bugs me is that I haven't yet been able to figure out how to do this Delphi Factory construct in C++.
The key part that I can't figure out is how to pass a reference to a class type in C++. In Delphi, we have "TClass" type. Variables of this type are a reference to some class. We can restrict the classes that a class reference can refer to using the class of MyClass
syntax to define a new class reference type.
Note that the term "Delphi class reference" =/= "C++ instance of a class"
For those unfamiliar with Pascal, variables are declared variable: type
rather than the C-style type variable
. Similarly, a function's return type appears after the parameter list and name.
I've condensed the syntax in the following example to make it less boilerplate-y, so apologies to Delphi devs for the terrible formatting. The key parts are described in comments.
program demo;
{$APPTYPE CONSOLE}
// declarations
type
Base = class
public constructor Create(name: string); virtual;
end;
// Class reference which refers to Base and its descendants
BaseClass = class of Base;
ChildA = class(Base)
public constructor Create(name: string); override;
end;
ChildB = class(Base)
public constructor Create(name: string); override;
end;
// implementation
constructor Base.Create(name: string);
begin
WriteLn('Base says hi to ' + name);
end;
constructor ChildA.Create(name: string);
begin
inherited Create(name);
WriteLn('ChildA says hi to ' + name);
end;
constructor ChildB.Create(name: string);
begin
WriteLn('ChildB says hi to ' + name);
end;
// *** THIS IS THE BIT THAT I'M INTERESTED IN ***
// The function doesn't know at compile time exactly what class it is being
// asked to construct. The compiler knows that it is or inherits from Base.
// I can't find any kind of "class reference" in C++.
function ConstructSomething(ClassType: BaseClass; name: string): Base;
begin
Result := ClassType.Create(name);
end;
// Equivalent to "main()" in C
begin
// Pass references to a class to the ConstructSomething function
ConstructSomething(Base, 'Mark');
WriteLn('');
ConstructSomething(ChildA, 'Mark');
WriteLn('');
ConstructSomething(ChildB, 'Mark');
WriteLn('');
end.
Output:
Base says hi to Mark
Base says hi to Mark
ChildA says hi to Mark
ChildB says hi to Mark
Note that when a reference to a child class is passed then the child class is created. Not calling the base constructor in ChildB is intentional in this demo, to make the "class reference" concept slightly more obvious.
The closest you can get is using a template function
template<typename ClassType>
Base* ConstructSomething(string name)
{
return new ClassType(name);
}
int main()
{
ConstructSomething<Base>("Mark");
ConstructSomething<ChildA>("Mark");
}
but ClassType
can't be selected at runtime - it must be known during compilation.