アロー演算子のオーバーロードの注意点
アロー演算子をオーバーロードして別のオブジェクトのポインタを返す処理があるとします。
以下のような感じです。
#include <iostream> using std::cout; using std::endl; class CMember { public: void output () { cout << "CMember::output" << endl; } }; class CClass { private: CMember* m_pCmember; public: CClass () { m_pCmember = new CMember; } ~CClass () { delete m_pCmember; } // アロー演算子をオーバーロードして別のオブジェクトを返す CMember* operator->() { return m_pCmember; } void output () { cout << "CClasss::output" << endl; } }; int main () { CClass* obj = new CClass; obj->output(); delete obj; return 0; }
さてこれを実行した場合、画面に表示されるのはCClass::outputでしょうか?CMember::outputでしょうか?
正解は・・・・
$ main CClasss::output
CClass::outputの方でした。アロー演算子をオーバーロードしているはずなのに何故こうなるんでしょうか。
答えは簡単です。obj変数はCClass型の変数ではなく、CClassのポインタ型だからです。
つまりobj変数は単なるポインタなのでCClassの影響を受けません。なので「obj->output()」におけるアロー演算子は「(*obj).output()」のシンタックスシュガーであり、アロー演算子でoutputを呼び出しているわけでは無いのでCClassの方のoutputが呼び出されたということになります。
なのでもしCMemberのoutputを呼び出したければ
(*obj)->output();
のように一旦間接参照してからアロー演算子で呼び出してやればよいということになります。
少し考えれば当たり前の話なのですが、コレのせいでハマってしまったので自戒を込めて。気をつけましょう。