メンバー アクセス演算子 、 などを除いて、ほとんどの演算子オーバーロードを理解して->
います.*
。->*
特に、これらの演算子関数には何が渡され、何が返されるのでしょうか?
演算子関数 (例operator->(...)
) は、参照されているメンバーをどのようにして知るのでしょうか? 知ることができるのでしょうか? そもそも知る必要があるのでしょうか?
最後に、const に関して考慮すべき事項はありますか? たとえば、 のようなものをオーバーロードする場合operator[]
、通常は const バージョンと非 const バージョンの両方が必要になります。メンバー アクセス演算子には const バージョンと非 const バージョンが必要ですか?
ベストアンサー1
->
これは本当にトリッキーな唯一のものです。これは非静的メンバー関数である必要があり、引数を取りません。戻り値はメンバー検索を実行するために使用されます。
戻り値がポインターではなく、クラス型の別のオブジェクトである場合、後続のメンバー検索も関数によって処理されます。これは「ドリルダウン動作」と呼ばれます。言語は、最後の呼び出しがポインターを返すまで呼び出しoperator->
を連結します。operator->
struct client
{ int a; };
struct proxy {
client *target;
client *operator->() const
{ return target; }
};
struct proxy2 {
proxy *target;
proxy &operator->() const
{ return * target; }
};
void f() {
client x = { 3 };
proxy y = { & x };
proxy2 z = { & y };
std::cout << x.a << y->a << z->a; // print "333"
}
->*
これは特別なことではないという点だけが難点です。過負荷ではないこのバージョンでは、左側にクラス型へのポインターのオブジェクト、右側にメンバー型へのポインターのオブジェクトが必要です。ただし、これをオーバーロードすると、任意の引数を取り、任意の値を返すことができます。非静的メンバーである必要さえありません。
つまり、これは、、、およびのような通常の二項演算子です+
。-
以下/
も参照してください。フリーのoperator->*オーバーロードは悪ですか?
.*
そして.
これらはオーバーロードできません。左側がクラス型の場合、すでに組み込みの意味があります。左側のポインターに対してこれらを定義できると少しは意味があるかもしれませんが、言語設計委員会はそれが便利というよりは混乱を招くと判断しました。
->
、、、->*
および.
のオーバーロードは.*
、式が未定義になる場合にのみ実行でき、オーバーロードなしで有効な式の意味を変更することはできません。