2012-01-08 13 views
89

(C++)、。何が返されるべきですか?オーバーロードメンバーアクセス演算子 - >、*これらの演算子関数に渡され、私はメンバアクセス演算子<code>-></code>、<code>.*</code>、特に<code>->*</code>など</p> <p>を除いて、ほとんどの演算子のオーバーロードを理解

どのメンバーが参照されているかをオペレータ機能(例:operator->(...))はどのように知っていますか?それは分かりますか?それは知る必要があるのでしょうか?

最後に、考慮する必要のあるconstに関する考慮事項はありますか?たとえば、operator[]のようなものをオーバーロードすると、一般にconstバージョンと非constバージョンの両方が必要になります。メンバーアクセスオペレータにはconstバージョンと非constバージョンが必要ですか?

+1

私は上記Qで質問されたすべてのQ ++を信じていると信じています。 –

+0

'operator'の' const'と ''const'のバージョンは*必須*ではありませんが、有用。 –

+1

も参照してください:http://yosefk.com/c++fqa/operator.html –

答えて

102

->

これは本当に難しいものです。これは、非静的メンバー関数でなければならず、引数をとらない。戻り値は、メンバー検索を実行するために使用されます。

戻り値がポインタではなくクラス型の別のオブジェクトである場合、後続のメンバー参照も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" 
} 

->*

それについて何も特別なことがないという点で、この1つは唯一のトリッキーです。 オーバーロードされていないバージョンでは、左側にクラス型へのポインタオブジェクトが、右側にメンバタイプへのポインタオブジェクトが必要です。しかし、あなたがそれをオーバーロードすると、好きな引数を取ってあなたが望むものを返すことができます。それは非静的メンバーである必要はありません。

つまり、+,-、および/のような通常の2進演算子です。参照:Are free operator->* overloads evil?

.*.

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

、および.*のみ式が未定義ことになる場合に記入することができ、それがオーバーロードしない有効だろう表現の意味を変更することはできません。

+2

あなたの最後の声明は完全に真実ではありません。例えば、オーバーロードされていなくても有効であっても、 'new'演算子をオーバーロードすることができます。 – Matt

+4

@Mattよく、 'new'は常にオーバーロードされています、またはオーバーロードルールはそれに実際には適用されません(13。5/5:割り当ておよび解放関数、演算子new、演算子new []、演算子削除および演算子 delete []は3.7.4で完全に説明されています。この の残りの部分にある属性と制限は、3.7.4で明示的に述べられていない限り、適用されません)。単項 '&'またはバイナリ '&&'、 '||'、または '、' 'operator ='のオーバーロードやスコープのない列挙型に対して何かのオーバーロードがあった場合、式の意味を変更することができます。声明を明確にしました、ありがとう! – Potatoswatter

8

オペレータは、どのメンバーがポイントされているのかわからず、実際のメンバーアクセスを実行するオブジェクトを提供するだけです。

また、constバージョンとnon-constバージョンを提供できない理由はありません。

5

演算子 - >()をオーバーロードすると(ここで引数が渡されません)、コンパイラは実際に型への実際のポインタを返すまで - >再帰的に呼び出します。その後、正しいメンバー/メソッドを使用します。

これは、実際のポインタをカプセル化するスマートポインタクラスを作成する場合などに便利です。オーバーロードされた演算子 - >が呼び出され、それが何であれ(例えば、スレッド安全のためにロックする)、内部ポインタを返し、コンパイラはこの内部ポインタに対して - >を呼び出します。

const-については、コメントやその他の回答で答えています。

+1

まさに私が探していたもの。ありがとう! – Andrew

20

オペレータ - >は特別です。

"ポインタの逆参照演算子も持つオブジェクト(またはオブジェクトへの参照)を返さなければならない、またはポインタの逆参照演算子の矢印を選択するために使用できるポインタを返す必要がある」と指摘している。 Bruce Eckel: Thinking CPP Vol-one : operator->

余分な機能は利便性のために提供されているので、あなたが

a->->func(); 

を呼び出す必要はありませんあなたは、単に行うことができます。

演算子を作る
a->func(); 

- 他のオペレータが異なります>過負荷。

+2

この回答はクレジットが必要です、そのリンクからEckelの本をダウンロードすることができ、その情報は第1巻第12章にあります。 –

20

メンバーアクセス.(つまり、->の2番目の部分)をオーバーロードすることはできません。ただし、参照先がの逆参照オペレータ*(つまり->の最初の部分)に上書きすることができます。

C++ ->演算子は基本的に2つのステップの和集合であり、x->y(*x).yと等価であると考えるならば、これは明らかです。 xがクラスのインスタンスである場合、C++では(*x)の部分の処理をカスタマイズできます。

->オーバーロードのセマンティックは、C++ではポインティングされたオブジェクトを見つけるために使用される通常のポインタを返すことができ、またはこのクラスでも->演算子を提供する場合は別のクラスのインスタンスを返すことができるため、 。この第2のケースでは、逆参照されたオブジェクトの検索がこの新しいインスタンスから継続されます。

+2

すばらしい説明!それは '(* x)。*'の形に相当するので、 ' - > *'と同じ意味であると思いますか? – Bingo

関連する問題