Переопределение операторов

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Переопределение операторов

Сообщение Vadim » 31.07.2018 12:30:36

Есть у меня сложный тип данных, к примеру такой:
Код: Выделить всё
Type
  TMyType = record
    id: integer;
    data: ^integer;
  end;

и я хочу для этого типа переопределить операторы +, -, *, / и в том числе присваивание. Сами понимаете, если переменные этого типа просто так присвоить друг другу, то присвоются адреса, а не значения. Если же попытаться переопределить оператор :=, то компилятор выдаёт такую ошибку:

Error: Impossible to overload assignment for equal types

хотя для арифметических операторов компилятор не ругается.
Переопределение операторов происходит вот так:
Код: Выделить всё
interface

operator + (op1: TMyType; op2: TMyType): TMyType;
operator := (op1: TMyType; op2: TMyType): TMyType;


Подскажите, как правильно.
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Переопределение операторов

Сообщение java73 » 31.07.2018 12:32:33

Кусок моего кода для дробей:
Код: Выделить всё
{ TFraction }

  TFraction = record
    Numerator: longint;
    Denumerator: longint;
    function Create(ANum, ADenum: longint): TFraction;
    function toStr: string;
    function toFloat: extended;
  end;

  TFrCompareResult = (crLeft, crRight, crEqual);

procedure SetEqualDenum(var ALeftFr, ARightFr: TFraction);
function ExpandFraction(AFraction: TFraction; Factor: longint): TFraction;
function gcd(ALeftDenum, ARightDenum: longint): longint;
function lcm(ALeftDenum, ARightDenum: longint): longint;
function CollapseFraction(AFraction: TFraction; Divider: longint = toGCD): TFraction;
function CompareFractions(ALeftFr, ARightFr: TFraction): TfrCompareResult;
function ReverseFraction(AFraction: TFraction): TFraction;
operator +(ALeftFr, ARightFr: TFraction) r: TFraction;
operator +(ALeftFr: TFraction; const Term: longint) r: TFraction;
operator -(ALeftFr, ARightFr: TFraction) r: TFraction;
operator -(ALeftFr: TFraction; const Sub: longint) r: TFraction;
operator * (ALeftFr, ARightFr: TFraction) r: TFraction;
operator * (AFraction: TFraction; const Multiplier: longint) r: TFraction;
operator * (const Multiplier: longint; AFraction: TFraction) r: TFraction;
operator / (ALeftFr, ARightFr: TFraction) r: TFraction;
operator / (AFraction: TFraction; const Divider: longint) r: TFraction;
operator = (ALeftFr, ARightFr: TFraction) r: boolean;
operator > (ALeftFr, ARightFr: TFraction) r: boolean;
operator < (ALeftFr, ARightFr: TFraction) r: boolean;
operator := (const AIntegerPart: longint) r: TFraction;
operator := (const AStringFr: string) r: TFraction;


Добавлено спустя 55 секунд:
Ругается потому, что параметр у оператора присваивания должен быть только один.

Добавлено спустя 3 минуты 55 секунд:
А если вы хотели, чтоб переменная такого типа создавалась подобным образом
Код: Выделить всё
Var1: TMyType
...
Var1 := (1, addr)

то так не выйдет. Самый короткий вариант - конструктор, как у меня.
java73
постоялец
 
Сообщения: 257
Зарегистрирован: 21.11.2013 09:08:10

Re: Переопределение операторов

Сообщение Дож » 31.07.2018 14:39:43

В стейблах нельзя перегрузить оператор присвоения из типа в себя.

В транке есть operator Copy, через который это вроде бы возможно.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Переопределение операторов

Сообщение java73 » 31.07.2018 14:46:08

Дож писал(а):operator Copy

да, но он не так работает
java73
постоялец
 
Сообщения: 257
Зарегистрирован: 21.11.2013 09:08:10

Re: Переопределение операторов

Сообщение sign » 01.08.2018 09:24:25

Vadim писал(а):Есть у меня сложный тип данных, к примеру такой:
Код: Выделить всё
Type
  TMyType = record
    id: integer;
    data: ^integer;
  end;

и я хочу для этого типа переопределить операторы +, -, *, / и в том числе присваивание. Сами понимаете, если переменные этого типа просто так присвоить друг другу, то присвоются адреса, а не значения.

Вам нужно переопределять оператор присваивания только когда вы присваиваетет другой тип, т.е., когда нужно переопределить результат!

Вот вам работающий пример.

Код: Выделить всё
unit Unit1;
type
  TMyType = record
    id: integer;
    data: ^integer;
  end;

  operator +(const T1, T2: TMyType): TMyType;
  operator :=(const T1: PInteger): TMyType;

implementation

operator + (const T1, T2: TMyType): TMyType;
begin
  Result.id := T1.id + T2.id;
  Result.data^ := T1.data^ + T2.data^ ;
end;

operator := (const T1: PInteger): TMyType;
begin
  Result.id := 0; // В любом случае, при присваивании вы потеряете исходное значение
  Result.data := T1;
end;

function MyType(aId: Integer; aAdr: PInteger): TMyType;
begin
  Result.id := aId;
  Result.data := aAdr;
end;

{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
var V1, V2, V3: TMyType;
    i1, i2, i3: Integer;
begin
  i1 := 1; i2 := 2; i3 := 100;
  V1 := MyType(10, i1);
  V2 := MyType(20, i2);
  V3.data := Addr(i3);
  V3 := V1 + V2;
end;

end.

Должен заметить, что адрес V3.data нужно определить до присваивания, иначе он указывает куда попало.
sign
энтузиаст
 
Сообщения: 1131
Зарегистрирован: 30.08.2009 09:20:53

Re: Переопределение операторов

Сообщение Дож » 01.08.2018 21:55:42

java73 писал(а):
Дож писал(а):operator Copy

да, но он не так работает

А как? Я смотрю сюда http://lists.freepascal.org/pipermail/f ... 36977.html и вижу, что operator Copy перегрузил оператор присвоения.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex [Bot] и гости: 1

Рейтинг@Mail.ru