Определение типов из других модулей в Delphi

Var
     A : Array [1..4] of Integer;
     B : Array [1..4] of Integer;

Begin
    A := B;

Не сработает, как сказала здесь Лорен-Печтель, проблема в том, что А и Б для меня в разных подразделениях. Итак, есть ли способ определить определение типа из существующего в другом классе?

8 ответов

Решение

Определите тип в интерфейсном блоке некоторого устройства, а затем включите его через uses пункт в других подразделениях, где вам нужен этот тип.

unit A;
interface
type
  TMyArray = array [1..4] of Integer;

...

Когда вам нужно использовать TMyArray в другом блоке:

unit B;
interface
uses A;

...
var x : TMyArray;

В качестве альтернативы, определите свой тип в разделе интерфейса блока C и используйте этот блок как в A, так и в B.

Типы массивов в Delphi немного странные. Похоже, A и B относятся к одному типу, но Delphi не считает, что они одинаковы. "Массив [1..4] of Integer" появляется дважды, поэтому Delphi считает, что есть два разных типа. Это просто странность Delphi. Большинство других языков, я думаю, не заботятся. На практике это не проблема; это просто немного странно. Может быть, для этого есть веская причина. Кто знает. Решение, как сказали другие, состоит в том, чтобы определить свой собственный тип, который вы можете поместить в модуль, который может использоваться другими модулями. Я просто упомянул эту проблему типов массивов, потому что это может сбить вас с толку.

Другой подход, немного устаревший, но все еще работающий, состоит в том, чтобы использовать ключевое слово ABSOLUTE, чтобы заставить один из них перекрывать другой и сделать совместимым другой тип. Например, в блоке а, скажем, у вас есть следующее:

TYPE
  TArrayA = Array[1..4] of integer;

тогда в блоке b у вас есть следующее:

TYPE
  TArrayB = Array[1..4] of integer;  

Для совместимости вы можете сделать следующее:

VAR
  InstanceA : TArrayA;
  InstanceB : TArrayB;
  InstanceBasA : TArrayA ABSOLUTE InstanceB;

Это создает переменную "InstanceBasA" типа ArrayA, которая перекрывает то же пространство памяти, что и переменная "InstanceB". Это позволяет вам выполнить следующую команду:

InstanceA := InstanceBasA;

Никогда, никогда, НИКОГДА не используйте код, подобный этому:

// This is where the move from ArrayA to ArrayB happens.
Move( ArrayA[1], ArrayB[1], SizeOf(ArrayA) );

Где недостаток? Вы используете размер SOURCE, чтобы получить количество байтов для перемещения, а не размер DESTINATION!!! Если SizeOf(A) > SizeOf(B), у вас переполнение буфера и вы перезаписываете память. Если вам повезет, вы получите AV, если нет, у вас есть уязвимость, которую можно использовать. Намного лучше всегда использовать конечный размер, хотя в этом случае вы можете в конечном итоге читать память, а не делать это, если Размер (B) > Размер (A), возможно, отображает нежелательные данные. В любом случае, всегда проверяйте границы структуры при перемещении данных - некоторые компании запретили такие операции (например, memcpy()) в своем коде.

Еще один метод перемещения данных из переменной a в переменную b - это использование команды MOVE. Например, чтобы перейти от ArrayA к ArrayB, вы можете сделать следующее:

var
  ArrayA : array[1..4] of Integer;
  ArrayB : Array[1..4] of Integer;
begin
  FillChar(ArrayB[1],SizeOf(ArrayB),#0);
  ArrayA[1] := 1234;
  ArrayA[2] := 3456;
  ArrayA[3] := 7890;
  ArrayA[4] := 9876;

  // This is where the move from ArrayA to ArrayB happens.
  Move( ArrayA[1], ArrayB[1], SizeOf(ArrayA) );

  Assert( ArrayA[4] = ArrayB[4], 'ArrayA[4] <> ArrayB[4]');
end;

Это работает благодаря тому факту, что массив расположен линейно, поэтому вы копируете байты, начиная с первой позиции массива, для длины массива.

Вы можете заставить компилятор предположить, что они принадлежат к одному и тому же типу, задав их тип:

type
  TIntArray = array[1..4] of integer;

begin
  Assert(SizeOf(ArrayA) = SizeOf(TIntArray));
  Assert(SizeOf(ArrayB) = SizeOf(TIntArray));
  TIntArray(ArrayA) := TIntArray(ArrayB);

Но вы должны убедиться, что оба на самом деле являются массивом [1..4], иначе вы перезапишете часть памяти. Вот почему я добавил два утверждения.

Просто используйте UnitA в UnitB после inteface и перед реализацией...!!!!

Другие вопросы по тегам