Jump to content
Michael Taylor

Class function vs constructor for object creation

Recommended Posts

I have a fairly simple class where the only members are an enumerated type and an object whose members are two integers and a string. Nothing that needs memory management, so I wanted to call my constructor "From" instead of "Create" to signify that no memory allocation takes place, and Free won't be necessary. However, this doesn't seem to work. I created an ObjectDictionary<ItemType, Span> and populated it with Span.From(...) and none of the objects seemed to be properly created (they were just junk data). When I replaced the From constructor with a From class function, it worked properly.

 

Can someone tell me what is happening in the class function that isn't happening in the constructor that is making it work?

 

Thank you!

 

{ Some things left out for brevity }

type
	Color = class
    public
    	property Red: Integer;
        property Green: Integer;
        property Blue: Integer;
        constructor From(r, g, b: Integer); overload;
        constructor From(hexVal: String); overload;
    end;

type
	ItemType = (A, B, C);
type
	Span = class
    public
    	property Color: Color;
        property item: ItemType;
        constructor From(item: ItemType, color: Color);
    end;

implementation

constructor Span.From(item: ItemType, color: Color);
begin
	Color := color;
    Item := item;
end;

{ The class function I replaced the constructor with.  This works. }
class function Span.From(item: ItemType, color: Color): Span;
begin
	result := Span.Create;
    result.Color := color;
    result.Item := item;
end;

 

Share this post


Link to post
14 minutes ago, Michael Taylor said:

I wanted to call my constructor "From" instead of "Create" to signify that no memory allocation takes place, and Free won't be necessary.

Naming the constructor "Create" is just a convention. You can name it anything you like.

Thus naming the constructor "From" will not make a difference.

 

Here's your problem:

20 minutes ago, Michael Taylor said:

 


constructor Span.From(item: ItemType, color: Color);
begin
  Color := color;
  Item := item;
end;

 

Pascal isn't case sensitive so that code does nothing.  Prefix your parameter names with "A" (i.e. name them AItem and AColor in this case) to avoid problems like that.

 

FWIW, if you want to avoid memory allocation (i.e. allocate your object on the stack instead of the heap), make it a record instead.

  • Thanks 1

Share this post


Link to post
8 hours ago, Michael Taylor said:

Nothing that needs memory management, so I wanted to call my constructor "From" instead of "Create" to signify that no memory allocation takes place, and Free won't be necessary.

This isn't true. Your class function calls the default constructor and that performs memory allocation. Free must be called. Instances of classes are heap allocated. 

  • Like 2

Share this post


Link to post
21 hours ago, David Heffernan said:

This isn't true. Your class function calls the default constructor and that performs memory allocation. Free must be called. Instances of classes are heap allocated. 

Doh, of course. That makes sense. Thank you, @David Heffernan!

Share this post


Link to post
On 8/27/2023 at 1:03 AM, Anders Melander said:

Prefix your parameter names with "A" (i.e. name them AItem and AColor in this case) to avoid problems like that

Or explicitly mark assignment to a field: Self.Item := Item

  • Like 1

Share this post


Link to post
On 8/26/2023 at 2:37 PM, Michael Taylor said:

I have a fairly simple class where the only members are an enumerated type and an object whose members are two integers and a string. Nothing that needs memory management

Standard strings are compiler-managed types. They are created dynamically and are also reference-counted, so the compiler needs to be able to manage and release them correctly.  Don't just let them leak.  Otherwise, use fixed-length character arrays if you really don't want to allocate their memory dynamically.

On 8/26/2023 at 2:37 PM, Michael Taylor said:

so I wanted to call my constructor "From" instead of "Create" to signify that no memory allocation takes place, and Free won't be necessary.

Instances of a Class are created dynamically and must be Destroy'ed/Free'd to avoid memory leaks.  Otherwise, use a Record instead of a Class.

  • Like 1

Share this post


Link to post
8 minutes ago, Anders Melander said:

Strange... It's like there's an echo in here.

It's the Dopplebeau effect. Normal. Don't even bother with it.

  • Haha 2
  • Sad 1

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×