Delphi の他のユニットからの型の定義
-
23-08-2019 - |
質問
Var
A : Array [1..4] of Integer;
B : Array [1..4] of Integer;
Begin
A := B;
ローレン・ペクテルが言ったようには機能しません ここ問題は、私にとって A と B が異なる単位にあることです。それでは、別のクラスの既存の型定義から型定義を定義する方法はあるのでしょうか?
解決
いくつかのユニットのインターフェイスブロックでタイプを定義し、次の方法でそのユニットを含めます。 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]」が 2 回出現するため、Delphi は 2 つの異なる型があると考えます。それは Delphi の単なる奇妙な点です。他のほとんどの言語は気にしないと思います。実際には問題ありません。それはちょっと不思議です。もしかしたらそれにはちゃんとした理由があるのかもしれない。知るか。他の人が言っているように、解決策は独自のタイプを定義し、それを他のユニットで使用できるユニットに入れることです。混乱を招く可能性があるため、配列型の問題についてのみ言及しました。
もう 1 つのアプローチは、少し古いですがまだ機能します。ABSOLUTE キーワードを使用して、一方の型のメモリを強制的に別の型にオーバーレイし、もう一方の型に互換性を持たせることです。たとえば、ユニット a に次のものがあるとします。
TYPE
TArrayA = Array[1..4] of integer;
ユニット b には次のものがあります。
TYPE
TArrayB = Array[1..4] of integer;
互換性を保つために、次のことができます。
VAR
InstanceA : TArrayA;
InstanceB : TArrayB;
InstanceBasA : TArrayA ABSOLUTE InstanceB;
これは、変数「InstanceB」と同じメモリ空間をオーバーレイする ArrayA 型の変数「InstanceBasA」を作成します。これにより、次のコマンドを実行できるようになります。
InstanceA := InstanceBasA;
データを変数 a から変数 b に移動するもう 1 つの方法は、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);
ただし、両方が実際には array[1..4] であることを確認する必要があります。そうしないと、メモリの一部が上書きされてしまいます。そのため、2 つの主張を追加しました。
あとは UnitA を UnitB で使用するだけです インターフェース そしてその前に 実装 ...!!!!
次のようなコードは絶対に絶対に使用しないでください。
// This is where the move from ArrayA to ArrayB happens.
Move( ArrayA[1], ArrayB[1], SizeOf(ArrayA) );
どこに欠陥があるのでしょうか?移動するバイト数を取得するには、DESTINATION サイズではなく、SOURCE サイズを使用しています。SizeOf(A) > SizeOf(B) の場合、バッファ オーバーフローが発生し、メモリが上書きされます。運が良ければ AV を入手できますが、そうでなければ悪用可能な脆弱性が存在します。常に宛先サイズを使用する方がはるかに優れていますが、この方法では、サイズ(B) > サイズ(A) の場合、読み込むべきではないメモリを読み取ってしまう可能性があり、不要なデータが公開される可能性があります。とにかく、データを移動するときは常に構造の境界を確認してください。一部の企業ではこのような操作を禁止しています(つまり、memcpy() ) コードから。