Перегрузка операций FPC 2.0.x | |||
Зачем это нужно | Как это сделать? | Примеры использования | |
Перегрузка функций | Вычисление многочлена матрицы | Реализация "больших" множеств | |
Вычисление квадратного корня из матрицы | |||
Зачем это нужно?
Очень часто при работе с типами данных, определенных пользователями, не хватает возможности работать с этими типами, как со встроенными в язык, т.е., например для сложения матриц не использовать вызов процедурыMatrixAdd(C, A, B);, а записать эту операцию в виде
C := A + B;
If isEqual(mx, mxO) or isEqual(mx, mxE), а
If (mx = mxO) or (mx = mxE)...
Как это сделать?
Прежде всего - чтобы перегрузка была доступна, программа (или модуль, если это делается в модуле) должна компилироваться с ключом {$mode objfpc}. При использовании модулей директива {$mode objfpc} обязательна только для модуля, содержащего реализацию перегрузки, вызывающая программа может такой директивы не иметь...Operator + (Const m1, m2: TMatrix) R: TMatrix; Begin { Заполняем матрицу R нужными значениями, и она вернется как результат операции } End;
Var A, B, C: TMatrix; Begin ... C := A + B; { матрица - сумма присвоится переменной C } ... End.
Перегрузка функций
function test(a: integer): integer; begin result := 0; end; { Разрешено - список параметров отличается от списка предыдущей функции } function test(a: double): integer; begin result := 0; end; { Ошибка: несмотря на то, что тип результата другой, списки параметров одинаковы, а это недопустимо } function test(a: integer): double; begin result := 0.0; end;
operator + (const mx1, mx2: TMatrix) r: TMatrix; var i, j: integer; begin for i := 1 to n do for j := 1 to n do r[i, j] := mx1[i, j] + mx2[i, j]; end;
operator + (const mx: TMatrix; const X: integer) r: TMatrix; var i, j: integer; begin for i := 1 to n do for j := 1 to n do r[i, j] := mx[i, j] + X; end;
Var A, B, C: TMatrix; Begin A := A + 2; C := A + B; End.
A := A + 2;это совсем не значит, что можно сделать и
A := 2 + A;
operator + (const X: integer; const mx: TMatrix) r: TMatrix; begin r := mx + X; { Пользуемся уже определенным сложением с другим порядком операндов } end;
Примеры использования:
1. Вычисление многочлена матрицы
{$mode objfpc} const size = 4; type TMatrix = array[1 .. size, 1 .. size] of double; operator * (const a, b: TMatrix) m: TMatrix; var i, j, k: integer; begin for i := 1 to size do for j := 1 to size do begin m[i, j] := 0; for k := 1 to size do m[i, j] := m[i, j] + a[i, k] * b[k, j] end; end; operator * (const a: TMatrix; const f: double) m: TMatrix; var i, j: integer; begin for i := 1 to size do for j := 1 to size do m[i, j] := f * a[i, j] end; operator + (const a, b: TMatrix) m: TMatrix; var i, j: integer; begin for i := 1 to size do for j := 1 to size do m[i, j] := a[i, j] + b[i, j] end; { Возведение матрицы в степень } operator ** (const a: TMatrix; const pow: integer) m: TMatrix; var i, j: Integer; begin if pow = 0 then begin for i := 1 to size do for j := 1 to size do m[i, j] := Byte(i = j); exit end; m := a; for i := 1 to pred(pow) do m := m * a; end; procedure matrixPrint(a: TMatrix); var i, j: integer; begin for i := 1 to size do begin for j := 1 to size do write(a[i, j]:9:2); writeln end end; const n = 3; p: array[1 .. n] of double = (1.0, -2.0, 3.0); const a: TMatrix = ( (10, 11, 14, 16), (12, 17, 10, 16), ( 8, 12, 12, 7), ( 8, 5, 17, 1) ); var Res: TMatrix; i: Integer; begin matrixPrint(a); for i := 1 to n do res := res + (a ** (n - i)) * p[i]; { Все вычисление записывается в одну строчку } matrixPrint(Res) end.