代入とコピー
クラスのインスタンスを定義してもその時点では実体はありません。
つまり、
Sample p;
は、Sampleクラスを入れるための箱としてpという変数を定義しただけになります。
この変数 p は、Sampleクラスのハンドルと呼びます。
この時点での変数 p の値は、nullです。
変数 p に実体を持たせるには、
p = new;
のようにSampleクラスのコンストラクタ(new関数)を実行すればいいのです。
この時点で変数 p は、Sampleクラスの実体を持つことになります。
次に、新しいSampleクラスのインスタンス q を定義します。
Sample q;
この時点で変数 q は、nullですね!では、変数 q に 変数 p を代入するとどうなるのでしょう!
q = p;
変数 q は、変数 p と同じ実体を持ちます(1つの実体を2つの変数が共有することになります)。
変数 q の内容を変更すると変数 p の内容が変わり、反対でも同じです。
では、同じ内容をコピーしたいときはどうすればいいのでしょうか?それは、
Sample s;
s = new p;
のように、コンストラクタの引数にコピーしたいインスタンスを渡せばいいのです。
これをシャドーコピー(Shadow Copy)と呼びます。
シャドーコピーでは、通常の変数(整数、浮動少数、文字列やインスタンスのハンドル)はコピーされますが、
オブジェクトはコピーされません。
下記の例では、SampleXクラスとSampleXクラスをインスタンス持つSampleYクラスを定義しています。
class SampleX;
int a;
function new;
a = 5;
endfunction
endclass : SampleX
class SampleY;
int b;
SampleX x;
function new;
b = 10;
x = new;
endfunction
endclass : SampleY
2つのSampleYクラスのインスタンスy1, y2を次のように生成し、
変数y1のメンバーx(SampleXクラスのインスタンス)のメンバーaに10を代入すると、
変数y2のメンバーx(SampleXクラスのインスタンス)のメンバーaも10になります。
なぜなら、変数y2のメンバーxはオブジェクトであるので、コピーされないで変数y1のメンバーxと同じだからです。
initial begin
SampleY y1;
SampleY y2;
y1 = new;
y2 = new y1;
y1.x.a = 10;
end
では、メンバー全部をコピーしたいときはどうすればいいのでしょうか?
下記の例のように、クラスにメンバー全部をきちんとコピーするメソッドを定義する必要があります。
(ちょっと、面倒ですね。。)
SampleZ z1;
SampleY z2;
z1 = new;
z2 = new;
z2.copy(z1);
SampleZクラスに、メソッドcopyを定義し、このメソッド内ですべてのメンバーのコピーを生成するようにする必要があります。