Arantium Maestum

プログラミング、囲碁、読書の話題

Effective C++勉強メモ: Item 24 右辺左辺どちらでも型変換が必要な可能性があるオペレータはNon-Member関数

ごくたまに暗黙の型変換が役にたつ時がある。特定の数字を表現するクラスを定義する時などである。

class Rational {
private:
  const int numerator, denominator;
public:
  Rational(int numerator = 0, int denominator = 1);
  const Rational operator*(const Rational& rhs) const;
}

Rational a(1, 2);
Rational b(3, 4);

Rational x = a * b;
Rational y = a * 2;
Rational z = 2 * b

有理数を表すRationalクラスが上記のように定義されていた場合、Rational * Rationalは問題なく実行できる。

Rational * IntRationalのコンストラクタが暗黙的にIntnumeratorとして受け取って型変換するのでoperator*が適用できる。

しかしInt * Rationalコンパイルエラーだ。なぜかというとRationalクラス内で定義されていたoperator*Rational演算子の左辺にある場合にのみ適用されるからである。そしてIntにはRationalとのoperator*は定義されていない。

class Rational {
private:
  const int numerator, denominator;
public:
  Rational(int numerator = 0, int denominator = 1);
}
const Rational operator*(const Rational& lhs, const Rational& rhs) { ... };

Rational型同士の掛け算をnon-memberなoperator*として定義すれば左辺がIntであっても暗黙の型変換が行われる。

ついでにいうとRationalクラスにnumerator/denominatorgetterが定義されていればFriend関数である必要もない。なるべくそのような設計になるよう心がけるべき。

Whenever you can avoid friend functions, you should, because, much as in real life, friends are often more trouble than they're worth - Scott Meyers

なんだかサイモン・アンド・ガーファンクルっぽいことを言っている・・・