【effective C++メモ】C++のexplicitキーワード

5894 ワード

explicitキーワードは、関数を構築するための明示的な宣言に使用されます.明示的と暗黙的の区別基準は、オブジェクトを定義する際に暗黙的な変換が使用されているかどうかです.まず簡単な例を見てみましょう.
int i = 2;
cout << (i + 3.5) << endl;

得られた結果は5.5であった.iはint型であり,1つのfloat小数と加算すると結果を暗黙的にfloat型に変換する.これに対応するのは強制変換、すなわち表示変換です.
クラスのコンストラクション関数では、暗黙的な変換もあります.次の例を見てください.
#include 
using namespace std;

class Rational
{
public:
    Rational(int numerator = 0, int denominator = 1);
    ~Rational(){}
    int get_n() const; //             
    int get_d() const;
protected:
private:
    int n;
    int d;
};

Rational::Rational(int numerator, int denominator)
                    :n(numerator), d(denominator){}

int Rational::get_n() const
{
    return n;   
}

int Rational::get_d() const
{
    return d;
}

int main()
{
    Rational ra1 = 12;
    Rational ra2 = Rational(12);
    cout << "rational 1 : " << ra1.get_n() <<"  / ” << ra1.get_d() << endl;
    cout << "rational 2 : " << ra2.get_n() < / " << ra2.get_d() << endl;
    system("pause");
    return 0;
}

mian()関数のRational ra1 = 12;Rational ra2 = Rational(12);は等価であり,1つ目は暗黙的変換である.
そうしないには、コンストラクション関数宣言時にexplicitを追加し、Rational ra1 = 12;という文で暗黙的な変換ができなくなり、エラーが発生し、コンストラクション関数を呼び出してオブジェクトを初期化するしかありません.
条項24:すべてのパラメータにタイプ変換が必要な場合は、non-member関数を使用します.次のコードがあります.
#include 
using namespace std;

class Rational
{
public:
     const Rational operator* (const Rational& rhs); //rhs      
     Rational(int numerator = 0, int denominator = 1);
    ~Rational(){}
    int get_n() const; //             
    int get_d() const;
protected:
private:
    int n;
    int d;
};

Rational::Rational(int numerator, int denominator)
                    :n(numerator), d(denominator){}

int Rational::get_n() const
{
    return n;   
}

int Rational::get_d() const
{
    return d;
}

const Rational Rational::operator *(const Rational &rhs)
{
    this->n = this->n * rhs.n;
    this->d = this->d * rhs.d;
    return *this;   
}

int main()
{
    Rational onehalf(1,2);
    Rational result;
    result = onehalf * 2;
    cout << "result : " << result.get_n() << " / " << result.get_d() << endl;
    system("pause");
    return 0;
}

このコードは有理数のクラスを宣言し、有理数と整数の演算を実現するために演算子を再ロードします.result = onehalf * 2は成功しますが、result = 2 * onehalfは失敗します.なぜですか.これはonehalfがオブジェクトであり、対応するoperator関数があり、数値2に遭遇すると、2を分子とするオブジェクトが暗黙的に変換され、積が実現されるためである.逆に、2という数値には対応するクラスがなく、operator*関数もありません.
同様に、コンストラクション関数でexplicitを宣言すると、result = onehalf * 2でもresult = 2 * onehalfでも失敗します.
良い方法は、リロードされた演算子をnon-member関数として使用することであり、member関数の反対側はfriend関数ではなくnon-member関数であることに注意してください.friend関数はいつでも避けることができるので、本当の世界のように、友达がもたらすトラブルは価値が多すぎることが多いので、避けてください.ええ...これは本当に言いにくいですね.