とりあえず、c++11 をある程度(言語が巨大なのでほんの少し)勉強してから、その上を勉強しようかなと思っているレベルの者です。
知りたいこと
c++ のクラスに、論理否定演算子「!」をオーバーロードする場合はどんな場合なのでしょうか?
例えば std::basic_ios では operator!() がオーバーロードされていますが、同時に、キャスト演算子 explicit operator bool() const;もオーバーロードされています。
しかし、operator bool() があれば、たとえexplicitがついていても、否定演算子!のオペランドの場合は明示的なキャストなしにbool型に変換されます。
またbool() と operator!() の両方がクラスAでオーバーロードされている場合、a が A のインスタンスのとき、!a と !static_cast<bool>(a) は同じ動作をするようにしないと使う方が混乱します。
とすると、多くの場合、 explicit operator bool() のみがあれば大丈夫のような気がするのですが、あえて 否定演算子のオーバーロードをする積極的な理由は何なのでしょうか?
たとえば、std::shared_ptr では!のオーバーロードはないようですね。
もし、論理演算子をオーバーロードする必用が在る場合でも「&&」「||」は短絡評価ができなくなるため危険ですから、普通は「!」しかできませんが。
自分でクラスを作るとき、!のオーバーロードを行うか否か?の指針が知りたいです。
試したこと
c++
1// test-not2.cpp 2#include <iostream> 3 4class A { 5public: 6 operator int() const {return 0;} // explicit をつけると当然のようにエラー 7}; 8 9class B { 10public: 11 explicit operator bool() const {return false;} 12}; 13 14class C { 15public: 16 bool operator!() const { return false;} 17}; 18 19class D { 20public: 21 explicit operator bool() const { 22 std::cerr << "D::operator bool()" << std::endl; 23 return false; 24 } 25 bool operator!() const { 26 std::cerr << "D::operator !()" << std::endl; 27 return false; 28 } 29}; 30 31 32using std::cout; 33using std::endl; 34 35int main(){ 36 A a; 37 B b; 38 C c; 39 D d; 40 41 cout << "!a: " << !a << endl; 42 cout << "!b: " << !b << endl; 43 cout << "!c: " << !c << endl; 44 cout << "!d: " << !d << endl; 45} 46
出力
bash@test-not2$ ./a.out !a: 1 !b: 1 !c: 0 !d: D::operator !() 0 bash@test-not2$
g++ (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
では、両方オーバーロードした場合、否定演算子が優先されたようです。
回答4件
下記のような回答は推奨されていません。
このような回答には修正を依頼しましょう。
2018/12/30 10:21 編集
2018/12/29 09:47
2018/12/29 10:24 編集
2018/12/30 10:17 編集
2018/12/30 10:29
2018/12/30 10:48