私の脳がゼリーに変わったか、という経験がありましたなどです。私は少しこのようになりますクラス階層をいじってる:
演算子と継承
マイMoney
クラスは次のようになります。
public abstract class Money
{
public int Amount { get; set; }
public static bool operator ==(Money leftSide, Money rightSide)
{
// Money can only be equal if it is in the same currency.
if (leftSide.GetType() != rightSide.GetType()) return false;
return leftSide.Amount == rightSide.Amount;
}
public static bool operator !=(Money leftSide, Money rightSide)
{
// If the currencies are different, the amounts are always considered unequal.
if (leftSide.GetType() != rightSide.GetType()) return true;
return leftSide.Amount != rightSide.Amount;
}
public static Money operator *(Money multiplicand, int multiplier)
{
var result = multiplicand * multiplier;
return result;
}
public static Dollar Dollar(int amount)
{
return new Dollar(amount);
}
public static Franc Franc(int amount)
{
return new Franc(amount);
}
}
マイドルoperator *
次のようになります。
public static Dollar operator *(Dollar multiplicand, int multiplier)
{
var result = multiplicand.Amount * multiplier;
return new Dollar(result);
}
今、このテストコードを実行すると、スタックオーバーフロー(wahoo!)が発生します。
{
Money fiveDollars = Money.Dollar(5);
Money timesTwo = fiveDollars*2;
}
これは、サブクラス(Dollar)operator *
を再帰的に呼び出すと予想していました。これは、(Dollar * int)が非再帰的に定義されているため、明確な結果を返します。これは機能しないので、私は何かばかげたやり方をしたことです。なぜこれは機能しませんか?この行動を取る正しい方法は何でしょうか?
スタックオーバーフローが発生したら、スタックを調べる必要があります。あなたは同じ機能が何度も何度も繰り返し呼び出しているのを見るでしょう。それだけで、何が起こっているのか、その理由について多くのことが分かります。 – abelenky
再帰は、あなたが実際に 'Dollar.operator *'ではなく 'Money.operator *'を呼び出すために起こることに注意してください。演算子は*オーバーロード*され、オーバーライド*されないので、呼び出される関数は*実行時*型ではなくオペランドの*コンパイル時*型によって決まります。 'fiveDollars'は' Money'型の変数であるので、 'fiveDollars * 2'は' operator'の 'Money'バージョンを呼び出します(' fiveDollars'のランタイム*タイプは 'Dollar'です)。 – dlev