2011-02-04 15 views
17

は、私のコードの例です:演算子オーバーロード - ここ>

class X 
{ 
public: 
     void f() {} 
}; 

class Y : public X 
{ 
public: 
     X& operator->() { return *this; } 
     void f() {} 
}; 

int main() 
{ 
     Y t; 
     t.operator->().f(); // OK 
     t->f(); // error C2819: type 'X' does not have an overloaded member 'operator ->' 
       // error C2232: '->Y::f' : left operand has 'class' type, use '.' 
} 

なぜコンパイラは、XにYから> operator-について「責任を動かす」しようとしていますか?私はX :: op->を実装すると、そこにXを返すことができません - コンパイルエラーはXからいくつかのZを返す間に "無限再帰"と言います:: op->再びZは演算子 - >を持たないので、階層的に高い

誰もこの興味深い行動を説明できますか? :)

答えて

18

問題がoperator ->ポインタ、ない参照を返すことになっていることです。その考え方は、operator ->は、ポインタが適用されるはずの実際のオブジェクトへのポインタを返さなければならないということです。例えば、過負荷にoperator ->を持つクラスのために、コード

myClass->myValue; 

(myClass.operator->())->myValue; 

に変換あなたのコードの問題はoperator ->がそう

myClass.operator->().f(); 

を書いて、参照を返すということですあなたが明示的に演算子を呼び出すが、書く場合は完全に合法ですが、書きます。

コンパイラは

myClass.operator->()->f(); 

に展開しようとしているとoperator->の戻り値の型がポインタではありませんので、

myClass->f(); 

は、違法です。

これを修正するには、operator ->にポインタを戻すようにコードを変更します。参照を返すように演算子をオーバーロードする場合は、オーバーロードoperator *;ポインタ逆参照は実際に参照を生成すべきです。

+9

私は 'それは' operator->をサポートするためのニーズを返すものは何でもちょうどこと、ポインタを返すと仮定だと言うではないでしょう。 – GManNickG

+1

@ GMan-良い点。私はここで簡単にするつもりだったが、あなたは正しい。このテクニックに依存しているスマートポインタを使用して、実際に楽しむことができるトリックがあります。 – templatetypedef

+0

@GMan:そのような型はまとめて*スマートポインタ*と呼ばれるので、templatypypedefは* pointer *という用語を使うのは間違っているとは思いません。 –

2

構文が間違っている、次のようになります。

T-> T2

T2* T::operator ->();​ 

Wikipediaの記事を見てみましょう。Operators in C and C++

あなたがオーバーロードしたい場合は、使用する必要があります。オーバーロードされたオペレータの正しい構文

19

->はC++で動作します。

オーバーロードされた->を使用すると、式a->ba.operator->()->bに変換されます。つまり、オーバーロードされた演算子->は、演算子->の別のアプリケーションをサポートするものを返す必要があります。このため、オーバーロードされた->の1回の呼び出しは、最終的にチェーンを終了する組み込みの->のアプリケーションに到達するまで、オーバーロードされた->の呼び出しの長い連鎖に変わる可能性があります。

をではなく->からオーバーロードして返す必要がある場合。

1

あなたはおそらくしたい:

class Y : public X 
{ 
public: 
     X* operator->() { return this; } 
     void f() {} 
}; 
関連する問題