C++ クラスメンバアクセス演算子 -> オーバーロード
クラスメンバアクセス演算子(->)はオーバーロードできますが、やや面倒です。これはクラスに「ポインタ」動作を与えるために定義されています。演算子 -> はメンバ関数でなければなりません。-> 演算子を使用する場合、戻り値の型はポインタまたはクラスのオブジェクトでなければなりません。
演算子 -> は通常、ポインタ参照演算子 * と組み合わせて使用され、「スマートポインタ」の機能を実装するために使われます。これらのポインタは、通常のポインタと似た動作を持つオブジェクトですが、ポインタを介してオブジェクトにアクセスするときに、他のタスクを実行する点が異なります。例えば、ポインタが破棄されたとき、またはポインタが別のオブジェクトを指すときに、オブジェクトを自動的に削除します。
間接参照演算子 -> は、単項後置演算子として定義できます。つまり、あるクラスが与えられた場合、
class Ptr{
//...
X * operator->();
};
类 Ptrそのオブジェクトは、クラスXのメンバーにアクセスするために使用でき、その使用法はポインタの使用法と非常に似ています。例えば:
void f(Ptr p )
{
p->m = 10 ; // (p.operator->())->m = 10
}
ステートメント p->m は (p.operator->())->m として解釈されます。同様に、以下の例はクラスメンバアクセス演算子 -> をオーバーロードする方法を示しています。
サンプル
#include <iostream>
#include <vector>
using namespace std;
// 実際のクラスを仮定する
class Obj {
static int i, j;
public:
void f() const { cout << i++ << endl; }
void g() const { cout << j++ << endl; }
};
// 静的メンバー定義
int Obj::i = 10;
int Obj::j = 12;
// 上記のクラスに対するコンテナを実装する
class ObjContainer {
vector<Obj*> a;
public:
void add(Obj* obj)
{
a.push_back(obj); // ベクターの標準的なメソッドを呼び出す
}
friend class SmartPointer;
};
// クラス Obj のメンバーにアクセスするためのスマートポインタを実装する
class SmartPointer {
ObjContainer oc;
int index;
public:
SmartPointer(ObjContainer& objc)
{
oc = objc;
index = 0;
}
// 戻り値はリストの終わりを表す
bool operator++() // 前置バージョン
{
if(index >= oc.a.size() - 1) return false;
if(oc.a[++index] == 0) return false;
return true;
}
bool operator++(int) // 後置バージョン
{
return operator++();
}
// 演算子 -> をオーバーロードする
Obj* operator->() const
{
if(!oc.a[index])
{
cout << "Zero value";
return (Obj*)0;
}
return oc.a[index];
}
};
int main() {
const int sz = 10;
Obj o[sz];
ObjContainer oc;
for(int i = 0; i < sz; i++)
{
oc.add(&o[i]);
}
SmartPointer sp(oc); // イテレータを作成する
do {
sp->f(); // スマートポインタ呼び出し
sp->g();
} while(sp++);
return 0;
}
上記のコードをコンパイルして実行すると、次の結果が生成されます:
10 12 11 13 12 14 13 15 14 16 15 17 16 18 17 19 18 20 19 21その他の拡張
C++ オーバーロード演算子とオーバーロード関数