Recent

Author Topic: Why Object Pascal Doesn't Let Operator Overloading In Classes?  (Read 8290 times)

İbrahim

  • New Member
  • *
  • Posts: 19
Why Object Pascal Doesn't Let Operator Overloading In Classes?
« on: September 30, 2017, 11:24:04 pm »
Hi; Why it doesn't let? Is problem memory leaks? Is this really? Can you explain more detail? Thanks.

cpicanco

  • Sr. Member
  • ****
  • Posts: 465
    • My Portfolio
Re: Why Object Pascal Doesn't Let Operator Overloading In Classes?
« Reply #1 on: September 30, 2017, 11:27:45 pm »
Can you give an example?

Leledumbo

  • Hero Member
  • *****
  • Posts: 8279
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: Why Object Pascal Doesn't Let Operator Overloading In Classes?
« Reply #2 on: October 01, 2017, 12:43:55 am »
https://stackoverflow.com/questions/2090472/why-isnt-operator-overloading-available-for-classes-in-delphi

Delphi NextGen compiler allows it, though, since it uses ARC so memory management becomes automatic.

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2532
    • havefunsoft.com
Re: Why Object Pascal Doesn't Let Operator Overloading In Classes?
« Reply #3 on: October 01, 2017, 02:08:47 am »
Can you implement the task without operator overloading?
Patron Cocoa Widgetset development https://www.patreon.com/skalogryz

Akira1364

  • Hero Member
  • *****
  • Posts: 542
Re: Why Object Pascal Doesn't Let Operator Overloading In Classes?
« Reply #4 on: October 01, 2017, 02:39:18 am »
Not really sure what you're talking about... FPC definitely supports operator overloading with classes just fine. Here's an example that works as expected:

Code: Pascal  [Select][+][-]
  1. program ClassOperatorOverloads;
  2.  
  3. type
  4.   TTestClass = class
  5.   public
  6.     IntegerA, IntegerB, AddedInteger: Integer;
  7.   end;
  8.  
  9.   operator +(const A, B: TTestClass): TTestClass;
  10.   begin
  11.     Result := TTestClass.Create;
  12.     Result.AddedInteger := A.IntegerA + B.IntegerB;
  13.   end;
  14.  
  15. var
  16.   TestClassA, TestClassB, TestClassC: TTestClass;
  17.  
  18. begin
  19.   TestClassA := TTestClass.Create;
  20.   TestClassA.IntegerA := 500;
  21.   TestClassB := TTestClass.Create;
  22.   TestClassB.IntegerB := 250;
  23.   TestClassC := TestClassA + TestClassB;
  24.   WriteLn(TestClassC.AddedInteger);  //This will display 750, of course...
  25.   TestClassA.Free;
  26.   TestClassB.Free;
  27.   TestClassC.Free;
  28.   ReadLn;
  29. end.

İbrahim

  • New Member
  • *
  • Posts: 19
Re: Why Object Pascal Doesn't Let Operator Overloading In Classes?
« Reply #5 on: October 01, 2017, 10:52:35 am »
Not really sure what you're talking about... FPC definitely supports operator overloading with classes just fine. Here's an example that works as expected:

Code: Pascal  [Select][+][-]
  1. program ClassOperatorOverloads;
  2.  
  3. type
  4.   TTestClass = class
  5.   public
  6.     IntegerA, IntegerB, AddedInteger: Integer;
  7.   end;
  8.  
  9.   operator +(const A, B: TTestClass): TTestClass;
  10.   begin
  11.     Result := TTestClass.Create;
  12.     Result.AddedInteger := A.IntegerA + B.IntegerB;
  13.   end;
  14.  
  15. var
  16.   TestClassA, TestClassB, TestClassC: TTestClass;
  17.  
  18. begin
  19.   TestClassA := TTestClass.Create;
  20.   TestClassA.IntegerA := 500;
  21.   TestClassB := TTestClass.Create;
  22.   TestClassB.IntegerB := 250;
  23.   TestClassC := TestClassA + TestClassB;
  24.   WriteLn(TestClassC.AddedInteger);  //This will display 750, of course...
  25.   TestClassA.Free;
  26.   TestClassB.Free;
  27.   TestClassC.Free;
  28.   ReadLn;
  29. end.

Thanks all, actually I'm talking about Delphi or Delphi mode. @Akira1364, I changed your example like this:
Code: Pascal  [Select][+][-]
  1. program ClassOperatorOverloads;
  2.  
  3. {$MODE OBJFPC}{$H+}
  4.  
  5. type
  6.   TTestClass = class
  7.   public
  8.     Number, AddedInteger: Integer;
  9.   end;
  10.  
  11.   operator +(const A, B: TTestClass): TTestClass;
  12.   begin
  13.     Result := TTestClass.Create;
  14.     Result.AddedInteger := A.Number + B.Number;
  15.   end;
  16.  
  17. var
  18.   TestClassA, TestClassB, TestClassC: TTestClass;
  19.  
  20. begin
  21.   TestClassA := TTestClass.Create;
  22.   TestClassA.Number := 500;
  23.   TestClassB := TTestClass.Create;
  24.   TestClassB.Number := 250;
  25.   TestClassC := TestClassA + TestClassB;
  26.   WriteLn(TestClassC.AddedInteger);  //This will display 750, of course...
  27.   TestClassA.Free;
  28.   TestClassB.Free;
  29.   TestClassC.Free;
  30. end.
  31.  
If you compile this example code with "fpc -gh ClassOperatorOverloads.pas" and run it, you'll see this output:
Code: Diff  [Select][+][-]
  1. 750
  2. Heap dump by heaptrc unit
  3. 3 memory blocks allocated : 48/48
  4. 3 memory blocks freed     : 48/48
  5. 0 unfreed memory blocks : 0
  6. True heap size : 32768
  7. True free heap : 32768
  8.  
There is not memory leak, okay. But if you change "TestClassC := TestClassA + TestClassB;" as "TestClassC := TestClassA + TestClassB + TestClassA;" and compile & run, you'll see this output:
Code: Diff  [Select][+][-]
  1. 500           // -----> WRONG RESULT
  2. Heap dump by heaptrc unit
  3. 4 memory blocks allocated : 64/64
  4. 3 memory blocks freed     : 48/48
  5. 1 unfreed memory blocks : 16
  6. True heap size : 32768
  7. True free heap : 32608
  8. Should be : 32624
  9. Call trace for block $00007F0AB0C90200 size 16
  10.   $00000000004002E2
  11.  
There is memory leak. How can I remove memory leak? Delphi developers don't recommend operator overloading in classes for this reason.

Cyrax

  • Hero Member
  • *****
  • Posts: 838
Re: Why Object Pascal Doesn't Let Operator Overloading In Classes?
« Reply #6 on: October 01, 2017, 11:14:53 am »
You can try if declaring TTestClass as subclass from TInterfacedObject class helps.

bytebites

  • Sr. Member
  • ****
  • Posts: 345
Re: Why Object Pascal Doesn't Let Operator Overloading In Classes?
« Reply #7 on: October 01, 2017, 01:09:20 pm »

There is not memory leak, okay. But if you change "TestClassC := TestClassA + TestClassB;" as "TestClassC := TestClassA + TestClassB + TestClassA;" and compile & run, you'll see this output:
Code: Diff  [Select][+][-]
  1. 500           // -----> WRONG RESULT
  2. Heap dump by heaptrc unit
  3. 4 memory blocks allocated : 64/64
  4. 3 memory blocks freed     : 48/48
  5. 1 unfreed memory blocks : 16
  6. True heap size : 32768
  7. True free heap : 32608
  8. Should be : 32624
  9. Call trace for block $00007F0AB0C90200 size 16
  10.   $00000000004002E2
  11.  
There is memory leak. How can I remove memory leak? Delphi developers don't recommend operator overloading in classes for this reason.

Change the addition and you get correct result:

Code: Pascal  [Select][+][-]
  1. operator +(const A, B: TTestClass): TTestClass;inline;
  2.   begin
  3.     Result := TTestClass.Create;
  4.     Result.Number := A.Number + B.Number;
  5.   end;  

Akira1364

  • Hero Member
  • *****
  • Posts: 542
Re: Why Object Pascal Doesn't Let Operator Overloading In Classes?
« Reply #8 on: October 01, 2017, 06:43:04 pm »
The reason you get a leak with adding three classes instead of two is because you're then creating an extra TTestClass instance that is never freed. There's no way around this other than to assign it to an actual variable and free it yourself.

I can't think of many cases where using three-parameter operator overloading with classes would even be a particularly good idea in the first place, also...
« Last Edit: October 01, 2017, 06:57:35 pm by Akira1364 »

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 8898
  • FPC developer.
Re: Why Object Pascal Doesn't Let Operator Overloading In Classes?
« Reply #9 on: October 01, 2017, 09:36:54 pm »
Basically if you have  c:=a+b, the intermediate value of a+b is also the total result.

If you have d:=a+b+c,  you have two an extra intermediate result; the one of a+b. And there is no reference to it anymore to free it

To avoid this, one can use

  • a not dynamically allocated type like record or TP TObject. No inheritance this way though
  • use automatically managed Interfaces
  • give all input classes a references to some master/mother class, then modify the operators so that the mother class gets a reference of newly created nodes. Then at the end, using the mother class, mark the nodes you want to keep and free the rest


ASerge

  • Hero Member
  • *****
  • Posts: 1693
Re: Why Object Pascal Doesn't Let Operator Overloading In Classes?
« Reply #10 on: October 01, 2017, 11:08:49 pm »
...a not dynamically allocated type like record or TP TObject. No inheritance this way though[/li][/list]
Misprint? Object has  inheritance. (Until now I do not understand why it was necessary to enter advanced records, if objects has everything too + inheritance + virtualization).

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 8898
  • FPC developer.
Re: Why Object Pascal Doesn't Let Operator Overloading In Classes?
« Reply #11 on: October 01, 2017, 11:15:21 pm »
    ...a not dynamically allocated type like record or TP TObject. No inheritance this way though[/li][/list]
    Misprint? Object has  inheritance.

    No misprint. There is no real inheritance/polymorphism in static usage. 

    ASerge

    • Hero Member
    • *****
    • Posts: 1693
    Re: Why Object Pascal Doesn't Let Operator Overloading In Classes?
    « Reply #12 on: October 02, 2017, 12:36:57 am »
    There is no real inheritance/polymorphism in static usage.
    What is static usage? I think in this example with inheritance only statics:
    Code: Pascal  [Select][+][-]
    1. {$APPTYPE CONSOLE}
    2. program Project1;
    3.  
    4. type
    5.   TAnsestor = object
    6.     F1: Integer;
    7.     procedure ShowField;
    8.   end;
    9.  
    10.   TDescendant = object(TAnsestor)
    11.     F2: Integer;
    12.     procedure ShowField;
    13.   end;
    14.  
    15. procedure TAnsestor.ShowField;
    16. begin
    17.   Writeln(F1);
    18. end;
    19.  
    20. procedure TDescendant.ShowField;
    21. begin
    22.   inherited;
    23.   Writeln(F2);
    24. end;
    25.  
    26. var
    27.   R: TDescendant;
    28. begin
    29.   R.F1 := 1;
    30.   R.F2 := 2;
    31.   R.ShowField;
    32.   Readln;
    33. end.

    marcov

    • Global Moderator
    • Hero Member
    • *****
    • Posts: 8898
    • FPC developer.
    Re: Why Object Pascal Doesn't Let Operator Overloading In Classes?
    « Reply #13 on: October 02, 2017, 01:00:54 pm »
    There is no real inheritance/polymorphism in static usage.
    What is static usage? I think in this example with inheritance only statics:

    Yes and no.

    Yes in that symbols are divided over multiple symbols with a relation between them, and you can inherit from a basetype.

    No, that you do anything interesting or OO with it, no Virtual usage or polymorphism of any kind.

    So maybe it is a form of inheritance, but it is not inheritance in the OO sense, where inheritance is the chosen vehicle of polymorphism for statically inherited OO languageimplementations.

    Is a record with a record helper then also inheritance ? No I know it is not entirely the same (the record helper cannot introduce own data), but it does satisfy the above rough "redivide symbols between two types with relation between them, but not the full OO definition", why is TObject different from that case?  Just because it has inheritance looking syntax?

    You also associate two types and not get the full set. And what if the record helper is inherited (trunk feature), is then the record also inherited ?  >:D
    « Last Edit: October 02, 2017, 01:03:37 pm by marcov »

    ASerge

    • Hero Member
    • *****
    • Posts: 1693
    Re: Why Object Pascal Doesn't Let Operator Overloading In Classes?
    « Reply #14 on: October 02, 2017, 07:14:37 pm »
    From https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming):
    Quote
    In object-oriented programming, inheritance is when an object or class is based on another object (prototypal inheritance) or class (class-based inheritance), using the same implementation. Inheritance in Java is a mechanism in which one object acquires all the properties and behaviors of parent object. The idea behind inheritance in Java is that you can create new classes that are built upon existing classes.[1] or specifying a new implementation to maintain the same behavior (realizing an interface). Such an inherited class is called a subclass of its parent class or super class. It is a mechanism for code reuse and to allow independent extensions of the original software via public classes and interfaces

    The object fully complies with this definition. Can a record with helpers do more? No.
    With virtual methods and the constructor, objects also support polymorphism:
    Code: Pascal  [Select][+][-]
    1. {$APPTYPE CONSOLE}
    2. program Project1;
    3.  
    4. type
    5.   PAnsestor = ^TAnsestor;
    6.   TAnsestor = object
    7.     F1: Integer;
    8.     procedure ShowField; virtual;
    9.     constructor Init;
    10.   end;
    11.  
    12.   PDescendant = ^TDescendant;
    13.   TDescendant = object(TAnsestor)
    14.     F2: Integer;
    15.     procedure ShowField; virtual;
    16.   end;
    17.  
    18. constructor TAnsestor.Init;
    19. begin
    20. end;
    21.  
    22. procedure TAnsestor.ShowField;
    23. begin
    24.   Writeln(F1);
    25. end;
    26.  
    27. procedure TDescendant.ShowField;
    28. begin
    29.   inherited;
    30.   Writeln(F2);
    31. end;
    32.  
    33. var
    34.   P: PAnsestor;
    35. begin
    36.   P := New(PDescendant, Init);
    37.   P^.F1 := 1;
    38. //  P^.F2 := 2; // Error by static check
    39.   P^.ShowField; // But dynamically everything works correctly
    40.   Dispose(P);
    41.   Readln;
    42. end.

    This is what I said at the beginning. Objects support inheritance and extended records are useless (in comparison with objects).

     

    TinyPortal © 2005-2018