Delphi: Default parameterless constructor

A weird consequence of Delphi’s OOP behavior is how constructors are handled, and in particular how the default parameterless constructor is handled.

Consider the following example:
[Delphi]
type
TMyClass = class
end;

var
Obj: TMyClass;

begin
Obj := TMyClass.Create();
Obj.Free();
end.
[/Delphi]
This code will actually compile and run. This happens because Create() constructor is inherited from TObject base class. So far, so good (actually it’s not that good, but at least we know what happens).

Now let’s define a parameterless private constructor (hoping to hide it like in other OOP languages):
[Delphi]
type
TMyClass = class
private
constructor Create();
end;

{ TMyClass }
constructor TMyClass.Create;
begin
end;

var
Obj: TMyClass;

begin
Obj := TMyClass.Create();
Obj.Free();
end.
[/Delphi]
This will again compile and run! But now, the actual TMyClass.Create() constructor will be called even if it’s private. It seems you cannot make a private version of the default constructor … Bad!

Third try: Let’s define a constructor with parameters and see what happens then:
[Delphi]
type
TMyClass = class
public
constructor Create(const AParameter: Integer);
end;

{ TMyClass }
constructor TMyClass.Create(const AParameter: Integer);
begin
end;

var
Obj: TMyClass;

begin
Obj := TMyClass.Create();
Obj.Free();
end.
[/Delphi]
OK, now we have a compilation error: “Not enough actual parameters” for TMyClass.Create() call. Well, that’s not exactly what we wanted, but it will do for now: we got rid of the default constructor!

And the final try, suppose you want a class that has more than one constructor:
[Delphi]
type
TMyClass = class
public
constructor Create(const AParameter: Integer); overload;
constructor Create(const AParameter: String); overload;
end;

{ TMyClass }
constructor TMyClass.Create(const AParameter: Integer);
begin
end;

constructor TMyClass.Create(const AParameter: String);
begin
end;

var
Obj: TMyClass;

begin
Obj := TMyClass.Create();
Obj.Free();
end.
[/Delphi]
Bad! — it compiles again.

It seems that no matter what I do, I can’t get rid of the default constructor! The only reasonable thing I can do is define a default constructor that just raises an Exception if it’s called.

Coming up next: Generic class restriction: “constructor”.

7 Comments

  1. I actually need a default constructor, and an overloaded constructor, and I just can’t call the default once another one is defined. Even after i explicitly declared and coded it, it always says “Not enough actual parameters” when i try to invoke it.

    I can’t think of this as anything else than a bug.

  2. Works for me 🙂 Here’s what I tried:
    type
    TClassA = class(TObject)
    public
    constructor Create(); overload;
    constructor Create(const A: String); overload;
    end;

    { TClassA }

    constructor TClassA.Create;
    begin

    end;

    constructor TClassA.Create(const A: String);
    begin

    end;

    var
    x: TClassA;

    begin
    x := TClassA.Create();
    end.

    Maybe you can paste your class if it’s different.

  3. omg, totally forgot about this problem and just moved on.
    let me see if i can find the class i was talking about.
    as arnold would say, “i’ll be back’.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.