05項 ユーザ定義の変換関数に気をつける

ユーザ定義の変換関数に気をつける



単一の引数を持つクラス、あるいは、複数の引数を持ち2番目以降の引数にデフォルト値があるクラスは、暗黙の型変換による危険があります。
本書の例を引用します。

template<class T>
class Array
{
public:
    Array(int size);

    T &operator[](int index);
    ...
}

bool operator=(const Array<int> &lhs, const Array<int> &rhs)

Array<int> a(10);
Array<int> b(10);

...
for (int i = 0; i < 10; i++)
{
    if(a == b[i]) //aとa[i]を間違えている
    {
        ...
    }
}

この例はエラーを発生させずにコンパイルされます。
"a == b[i]"の部分は"a == Array"に、暗黙的な型変換がされているからです。
対策は、コンストラクタにexplicitを指定することです。explicitは、暗黙的な型変換を禁止します。

template<class T>
class Array
{
public:
    explicit Array(int size);

    T &operator[](int index);
    ...
}

コンパイラが古くexplicitに対応してない場合の対策が本書に掲載されていますが、省略します。



もうひとつ、キャスト演算子にも注意します。

class Rational
{
public:
	Rational(int numerator = 0, int denominator = 1);
	
	
	operator double() const; //キャスト演算子
	...
};


...
Rational r(1, 2);
cout << r; // 1/2と出力したいが、
      // <<演算子をオーバロードしてない場合
      // 0.5が出力される。

対策は、operator doubleをasDoubleのような名前の関数に置き換え、型変換の明示的な呼び出しを強制することです。

class Rational
{
public:
	Rational(int numerator = 0, int denominator = 1);
	
	
	double asDouble() const;
	...
};