3

次のコードを検討してください。

class Truth
{
public:
    Truth(bool val) : value(val) {}
    bool operator!() {std::cout<<"operator!()"<<std::endl; return !value;}
    operator bool() {std::cout<<"operator bool()"<<std::endl; return value;}
private:
    bool value;
};

int main()
{
    Truth t(true);

    if(!t)
        std::cout<<"t is false"<<std::endl;
    else
        std::cout<<"t is true"<<std::endl;

    if(!!t)
        std::cout<<"t is false"<<std::endl;
    else
        std::cout<<"t is true"<<std::endl;

    if(t)
        std::cout<<"t is false"<<std::endl;
    else
        std::cout<<"t is true"<<std::endl;

    return 0;
}

ステートメントif(!t)if(!!t)は、オーバーロードされたoperator!()実装が呼び出されますが、(驚くべきことではありませんが) ステートメントでは、代わりにif(t)オーバーロードされたoperator bool()実装が呼び出されます。

ただし、operator!()実装がコメントアウトされている場合は、3 つのステートメントすべてでoperator bool()呼び出されます。

これが発生する「理由」は理解していますが、私の懸念は、論理 NOT 演算子 (!) をオーバーロードすると、真偽評価のセマンティクスの半分が失われているように見えますが、bool型キャスト演算子はそれらをうまくカバーしているように見えます。

何か不足していますか、それともブール型キャストを優先して論理 NOT 演算子のオーバーロードをやめるべきですか?

4

1 に答える 1

5

C++11 では、単純にオーバーロードできますexplicit operator bool()operator!何か違うことをしたくないのでなければ、オーバーロードする理由はありません。

歴史的に、オーバーロードoperator boolは任意の数値型への暗黙的な変換への扉を開き、混乱、あいまいさ、および微妙なバグを引き起こす可能性がありました。だからやらないほうがよかった。オーバーロードは、安全な bool イディオムoperator!に行き詰まりたくない場合に、そのドアを開かずに条件文で使用できるようにする簡単な方法でした。(リンクは歴史的な関心のみを目的としています。明示的な変換演算子のおかげで、イディオムは C++11 では廃止されています。)

于 2014-02-25T02:05:08.573 に答える