Перекрестная ссылка между записями delphi - PullRequest
3 голосов
/ 11 марта 2010

Допустим, у меня есть запись TQuaternion и запись TVector. У кватернионов есть несколько методов с параметрами TVector. С другой стороны, TVector поддерживает некоторые операции с параметрами TQuaternion.

Зная, что Delphi (Win32) не допускает объявлений пересылки записей , как мне решить эту проблему элегантно?

Использование классов на самом деле не вариант здесь, потому что я действительно хочу использовать перегрузку оператора для этого редкого случая, когда это действительно имеет смысл.

А пока я просто переместил эти конкретные методы из записей в отдельные функции, старомодным способом. Лучшие предложения приветствуются.

Ответы [ 4 ]

3 голосов
/ 11 марта 2010

Если операторы не являются реальной проблемой, вы можете решить эту проблему с помощью помощника по записи.

type
  TVector = record
  end;

  TQuaternion = record
    procedure UseVector(var V: TVector);
  end;

  TVectorHelper = record helper for TVector
    procedure UseQuaternion(var Q: TQuaternion);
  end;

Это решит только круговые зависимости и не работает с операторами. Недостатком также является то, что у вас нет другого помощника по записи для TVector, по крайней мере, они не могут быть доступны в одном месте.

3 голосов
/ 11 марта 2010

В общем, элегантного решения не существует, только старые хаки с нетипизированными ссылками вроде этого:

type
  TVector = record
    procedure UseQuaternion(var Q);
  end;

  TQuaternion = record
    procedure UseVector(var V: TVector);
  end;

{ TVector }

procedure TVector.UseQuaternion(var Q);
var
  Quaternion: TQuaternion absolute Q;

begin
  Quaternion.UseVector(Self);
end;

{ TQuaternion }

procedure TQuaternion.UseVector(var V: TVector);
begin

end;

Для особых случаев может быть полезен следующий шаблон:

type
  TVectorData = array [0..1] of Double;
  TQuaternionData = array [0..3] of Double;

  TVector = record
    Data: TVectorData;
    procedure UseQuaternion(var Q: TQuaternionData);
  end;

  TQuaternion = record
    Data: TQuaternionData;
    procedure UseVector(var V: TVector);
  end;
2 голосов
/ 11 марта 2010

Я думаю, что ваше «старомодное» решение лучше.
как альтернативное решение - но приводящее к схеме вашего решения - как насчет Записи, содержащей две ваши записи и методы как методы основной Записи:

type  
  TQuaternionVector = record  
    Vector: TVector;  
    Quaternion: TQuaternion;  
    procedure F(V: TVector; Q: TQuaternion);    
  end;
1 голос
/ 11 марта 2010

Для конкретного случая, когда требуется использовать перегрузку операторов (и, более конкретно, двоичные операторы), типы записей, с которыми вы работаете, могут быть указаны в любом порядке.

Приведенные ниже объявления позволят вам добавлять векторы и кватернионы (если это имеет смысл :-)) в любой комбинации (3-е объявление Add для TQuaternion является интересным):

type
  TVector = record
    class operator Add( v1, v2 : TVector ) : TVector;
    end;

  TQuaternion = record
    class operator Add( q1, q2 : TQuaternion ) : TQuaternion;
    class operator Add( q : TQuaternion; v : TVector ) : TQuaternion;
    class operator Add( v : TVector; q : TQuaternion ) : TQuaternion;
    end;

При условии объявления соответствующих переменных следующие все компиляции:

q1 := q2 + q3;
v1 := v2 + v3;

q1 := q2+v2;
q2 := v2+q2;

Этого достаточно, чтобы покрыть то, что вам нужно?

...