1. ホーム
  2. c++

[解決済み] メンバアクセス演算子 ->, .* のオーバーロード

2022-05-08 08:18:02

質問

ほとんどの演算子のオーバーロードを理解しているが、メンバーアクセス演算子は例外である。 -> , .* , ->* などです。

具体的には、これらの演算子関数に何が渡され、何が返されるべきなのでしょうか?

演算子関数(例えば operator->(...) は、どのメンバが参照されているのかを知っていますか?知ることができるでしょうか?知る必要があるのでしょうか?

最後に、考慮しなければならない制約事項がありますか?例えば、以下のようなオーバーロードをする場合 operator[] 一般的には、constとnon-constの両方が必要です。メンバアクセス演算子にもconst版とnon-const版が必要なのでしょうか?

どのように解決するのですか?

->

これが唯一、本当に厄介なものです。これは非静的なメンバ関数でなければならず、引数も取りません。戻り値はメンバ検索を行うために使用されます。

戻り値がポインタではなく、クラス型の別のオブジェクトである場合、その後のメンバ検索も operator-> 関数があります。これはドリルダウン動作と呼ばれます。 operator-> を呼び出すと、最後の1つがポインタを返します。

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->*オーバーロードは悪なのか?

.*.

これらはオーバーロードすることができません。左辺がクラス型の場合は、すでに組み込みの意味があります。おそらく、左辺のポインタに対して定義できるようにすれば少しは意味があるのでしょうが、言語設計委員会は、それは有用というよりも混乱を招くと判断しました。

オーバーロード -> , ->* , . および .* は、式が未定義になるケースを埋めることができるだけで、オーバーロードがなくても有効な式の意味を変えることはできません。