Type TList = Object Private first, last: ptitem; Function isEmpty: Boolean;
Public
Constructor Create; Destructor Destroy; Virtual;
Procedure append(x: T); Procedure insert(x: T);
Procedure Print; End;
Operator + (Const L: TList; it: T) R: TList; Begin L.append(it); result := L; End; Operator + (it: T; Const L: TList) R: TList; Begin L.insert(it); result := L; End;
Constructor titem.init(x: T; nxt, prv: ptitem); Begin info := x; next := nxt; prev := prv; End;
Destructor titem.done; Begin End;
(* tlist *) Constructor TList.Create; Begin first := nil; last := nil; End;
Destructor TList.Destroy; Begin // ... End;
Function TList.isEmpty: Boolean; Begin isEmpty := (first = nil); End;
{ insert new item to the start of list } Procedure TList.insert(x: T); Var p: ptitem; Begin new(p, init(x, first, nil)); If p <> nil Then Begin
If isEmpty Then last := p Else first^.prev := p;
first := p;
End; End;
{ append new item to the end of list } Procedure TList.append(x: T); Var p: ptitem; Begin new(p, init(x, nil, last)); If p <> nil Then Begin
If isEmpty Then first := p Else last^.next := p;
last := p;
End; End;
Procedure TList.Print; Var pt: ptitem; Begin Write('<'); pt := first; While pt <> nil Do Begin write(pt^.info, ' '); pt := pt^.next End; WriteLn('>') End;
var list_int: TList; i: integer;
begin list_int.create;
// Здесь работаем по-старинке: list_int.insert(10); // Добавляем элемент в начало списка list_int.insert(20); // ... list_int.append(30); // Добавляем элемент в конец списка list_int.append(40); // ... list_int.print;
// А здесь - используем возможности современного компилятора - // перегрузку операций for i := 1 to 8 do list_int := (15 * i) + list_int + (10 * i);
list_int.print; list_int.destroy; end.
Все компилируется и работает. Меня интересует такой вопрос: насколько удобно будет пользователю библиотеки перейти от привычной формы записи (в виде процедур) к записи вида:
ListObj := 12 + 17 + ListObj + 24 + 32 + 78; { <--- Это, кстати, тоже работает... }
, и стоит ли вообще предоставлять ему такую возможность и заморачиваться с перегрузкой операций?
Еще кое-что... Тип T не всегда будет Integer, вполне возможно, что там будет указатель на какой-то объект. Вопрос, собственно, в том, распространяются ли на operator overloading правила наследования, то есть, смогу ли я передавать левым/правым операндом, например, указатели на объекты, находящиеся на разном уровне иерархии наследования, или только указатель на базовый класс?