Recent

Author Topic: [SOL.]How to leave constructor early (and destroy instance) if condition is met?  (Read 1757 times)

BrainChemistry

  • Jr. Member
  • **
  • Posts: 72
Hello everybody,

simple question, see title:

Code: Pascal  [Select][+][-]
  1. //interface
  2. Test = class
  3.   constructor Create(APar: Pointer);
  4. //...
  5.  
  6. // implementation
  7. constructor Test.Create(APar: Pointer);
  8. begin
  9.   inherited Create;
  10.   if not Assigned(APar) then // then how to proceed?
  11.   begin
  12.     Exit;
  13.     FreeAndNil(Self);
  14.   end;
  15. //...
  16.  

I made a long research on the internet on this and I get to believe perhaps my design is flawed because all I found was how to handle exceptions in the constructor.

Thanks for your help in advance.
« Last Edit: May 21, 2020, 09:21:57 pm by BrainChemistry »

GetMem

  • Hero Member
  • *****
  • Posts: 3743
Check if the pointer is nil before you create an instance of TTest class, like this:
Code: Pascal  [Select][+][-]
  1. var
  2.   Test: TTest;
  3. begin
  4.   if APar <> nil then
  5.   begin
  6.      Test := TTest.Create(APar);
  7.      //...
  8.   end
  9.   else
  10.     DoSomethingElse;
  11. end;
  12.  

eljo

  • Sr. Member
  • ****
  • Posts: 408
Hello everybody,

simple question, see title:

Code: Pascal  [Select][+][-]
  1. //interface
  2. Test = class
  3.   constructor Create(APar: Pointer);
  4. //...
  5.  
  6. // implementation
  7. constructor Test.Create(APar: Pointer);
  8. begin
  9.   inherited Create;
  10.   if not Assigned(APar) then // then how to proceed?
  11.   begin
  12.     Exit;
  13.     FreeAndNil(Self);
  14.   end;
  15. //...
  16.  

I made a long research on the internet on this and I get to believe perhaps my design is flawed because all I found was how to handle exceptions in the constructor.

Thanks for your help in advance.
raise an exception. Any exception raised in a constructor will clean up any memory allocation. It is taken care by the framework.

Thaddy

  • Hero Member
  • *****
  • Posts: 10271
"nice" piece of coding:
what will happen here?
Code: Pascal  [Select][+][-]
  1. constructor Test.Create(APar: Pointer);
  2. begin
  3.   inherited Create;
  4.   if not Assigned(APar) then // then how to proceed?
  5.   begin
  6.     Exit; // <=== Huh?
  7.     FreeAndNil(Self); // dead code...
  8.   end;
I am more like donkey than shrek

Thaddy

  • Hero Member
  • *****
  • Posts: 10271
more idiocy ( I am mad enough thank you..(true))
Quote
raise an exception
In a constructor?, really???
Then you should also handle the exception inside the constructor....
« Last Edit: May 21, 2020, 06:52:14 pm by Thaddy »
I am more like donkey than shrek

eljo

  • Sr. Member
  • ****
  • Posts: 408
more idiocy ( I am mad enough thank you..(true))
Quote
raise an exception
In a constructor?, really???
Then you should also handle the exception inside the constructor....
Yes in the constructor. Prove me wrong if you can. I'll report the bug my self if you do.

Thaddy

  • Hero Member
  • *****
  • Posts: 10271
That is not even close to a serious reply eljo
I am more like donkey than shrek

eljo

  • Sr. Member
  • ****
  • Posts: 408
That is not even close to a serious reply eljo
Yes, because calling me an idiot mandates a far better response.

As I said, raising an exception in the constructor, will exit the constructor with out creating the object. It is what the OP asked for. If you have more info on the subject that I missed, please fill free to share with us.
« Last Edit: May 21, 2020, 07:52:30 pm by eljo »

julkas

  • Hero Member
  • *****
  • Posts: 619
  • KISS principle / Lazarus 2.0.6 / FPC 3.0.4
I agree with @GetMem.
procedure mulu64(a, b: QWORD; out clo, chi: QWORD); assembler;
asm
  mov rax, a
  mov rdx, b
  mul rdx
  mov [clo], rax
  mov [chi], rdx
end;

eljo

  • Sr. Member
  • ****
  • Posts: 408
I agree with @GetMem.
Me too but that assumes that the OP has control over the code that creates the object what happens if he is responsible for the class but not how its used?

julkas

  • Hero Member
  • *****
  • Posts: 619
  • KISS principle / Lazarus 2.0.6 / FPC 3.0.4
procedure mulu64(a, b: QWORD; out clo, chi: QWORD); assembler;
asm
  mov rax, a
  mov rdx, b
  mul rdx
  mov [clo], rax
  mov [chi], rdx
end;

GetMem

  • Hero Member
  • *****
  • Posts: 3743
@eljo
Quote
Me too but that assumes that the OP has control over the code that creates the object what happens if he is responsible for the class but not how its used?
Good point. I did not think about this particular situation. In my opinion raising an exception inside the constructor is a perfectly valid solution.

Bart

  • Hero Member
  • *****
  • Posts: 3850
    • Bart en Mariska's Webstek
You can call Fail inside a constructor.
The constructor will return Nil in that case.

Code: Pascal  [Select][+][-]
  1. constructor TMyClass.Create;
  2. begin
  3.   if SomeCriticalConditionIsNotMet then
  4.     Fail;
  5.   ...
  6.   //rest of constructor code
  7. end;
  8.  
  9. ...
  10. var
  11.   C: TMyClass;
  12. begin
  13.   C := nil;
  14.   C := TMyClass.Create;
  15.   if C = nil then ErrorMessageAndHaltApplication;
  16.   //Do something with C
  17.   C.Free;
  18. end..

There wil be no memory leak (for the instance of C, that is).

Bart
« Last Edit: May 21, 2020, 09:12:37 pm by Bart »

BrainChemistry

  • Jr. Member
  • **
  • Posts: 72
Check if the pointer is nil before you create an instance of TTest class, like this:
Code: Pascal  [Select][+][-]
  1. var
  2.   Test: TTest;
  3. begin
  4.   if APar <> nil then
  5.   begin
  6.      Test := TTest.Create(APar);
  7.      //...
  8.   end
  9.   else
  10.     DoSomethingElse;
  11. end;
  12.  

Quote from: eljo
but that assumes that the OP has control over the code that creates the object what happens if he is responsible for the class but not how its used?

That is exactly the case, hence it is unfortunately no option to check the condition outside the constructor.

@eljo: I read about having an exception raised to stop the instance from being created (and memory cleaned up) in my research before. Maybe it is just me, but this feels like a dirty trick and an abuse of the exception mechanism.

Is there a "clean way" of interrupting the instance creation?

REMARK: While writing this, this came in:

You can call Fail inside a constructor.
The constructor will return Nil in that case.

Code: Pascal  [Select][+][-]
  1. constructor TMyClass.Create;
  2. begin
  3.   if SomeCriticalConditionIsNotMet then
  4.     Fail;
  5.   ...
  6.   //rest of constructor code
  7. end;
  8.  
  9. ...
  10. var
  11.   C: TMyClass;
  12. begin
  13.   C := nil;
  14.   C := TMyClass.Create;
  15.   if C = nil then ErrorMessageAndHaltApplication;
  16.   //Do something with C
  17.   C.Free;
  18. end..

There wil be no memory leak (for the instance of C, that is).

Bart

That's what I was looking for! Thanks Bart and everybody!



julkas

  • Hero Member
  • *****
  • Posts: 619
  • KISS principle / Lazarus 2.0.6 / FPC 3.0.4
procedure mulu64(a, b: QWORD; out clo, chi: QWORD); assembler;
asm
  mov rax, a
  mov rdx, b
  mul rdx
  mov [clo], rax
  mov [chi], rdx
end;

 

TinyPortal © 2005-2018