コレクションの全メンバへのアクセス
更新 : 2007 年 11 月
MFC の配列コレクション クラスでは、テンプレート クラスでも非テンプレート クラスでも、インデックスを使って要素にアクセスします。MFC のリスト コレクション クラスおよびマップ コレクション クラスでは、テンプレート クラスでも非テンプレート クラスでも、POSITION 型のインジケータを使ってコレクション内の位置を指定します。これらのコレクションの 1 つ以上のメンバにアクセスするには、まず、ポジション インジケータを初期化し、次にそのポジションを繰り返しコレクションに引き渡して、次の要素の位置を問い合わせます。コレクションは、繰り返しの進行についての状態情報を保持していません。この情報は、ポジション インジケータで保持します。一方、コレクションは、指定されたポジションの次の要素を返します。
次に、MFC が提供する代表的な 3 種類のコレクションに対する繰り返し処理について説明します。
配列に繰り返しアクセスするには
リストに繰り返しアクセスするには
マップに繰り返しアクセスするには
配列に繰り返しアクセスするには
連続したインデックス番号を指定して、GetAt メンバ関数を呼び出します。
CTypedPtrArray<CObArray, CPerson*> myArray; myArray.Add(new CPerson()); for (int i = 0; i < myArray.GetSize();i++) { CPerson* thePerson = myArray.GetAt(i); thePerson->AssertValid(); }
この例では、CPerson オブジェクトへのポインタを格納する型付きポインタ配列を使っています。この配列の基本クラスは、定義済みの非テンプレート クラスである CObArray クラスです。GetAt は、CPerson オブジェクトへのポインタを返します。型付きポインタ コレクション クラスの場合は、配列でもリストでも、最初のパラメータで基本クラスを指定し、2 番目のパラメータで格納するデータの型を指定します。
CTypedPtrArray クラスでは、さらに [ ] 演算子をオーバーロードして、配列の要素を従来の添字付け構文でもアクセスできます。上の for ループ本体の文は、次のように書き換えることができます。
CPerson* thePerson = myArray[i];
この演算子は const 版と非 const 版があります。const 版は、const の配列に使われ、代入文の右辺に書くことができます。
リストに繰り返しアクセスするには
リスト内の項目を順に処理するには、GetHeadPosition と GetNext の 2 つのメンバ関数を使用します。
CTypedPtrList<CObList, CPerson*> myList; myList.AddHead(new CPerson()); POSITION pos = myList.GetHeadPosition(); while(pos != NULL) { CPerson* thePerson = myList.GetNext(pos); thePerson->AssertValid(); }
この例では、型付きポインタ配列に CPerson オブジェクトへのポインタを格納します。リストの宣言は、「配列に繰り返しアクセスするには」の配列宣言に似ていますが、基本クラスとして CObList クラスを使用します。GetNext 関数は CPerson オブジェクトへのポインタを返します。
マップに繰り返しアクセスするには
GetStartPosition でマップの先頭位置を取得し、GetNextAssoc でマップから次のキーと値を順次取得します。次に例を示します。
CMap<CString, LPCTSTR, CPerson*, CPerson*> myMap; CPerson myPerson; myMap.SetAt(_T("Bill"), &myPerson); POSITION pos = myMap.GetStartPosition(); while(pos != NULL) { CPerson* pPerson; CString string; // Get key (string) and value (pPerson) myMap.GetNextAssoc(pos, string, pPerson); // Use string and pPerson }
この例では、型付きポインタ コレクションではなく、簡単なマップ テンプレートを使用しています。このテンプレートは、CString 型のキーを使用し、CPerson オブジェクトへのポインタを格納します。GetNextAssoc などのアクセス関数を使用すると、CPerson オブジェクトへのポインタが返されます。代わりに非テンプレート マップ コレクションを使用すると、CObject へのポインタが返されるので、CPerson へのポインタに型キャストする必要があります。
メモ : 非テンプレート マップの場合、コンパイラは GetNextAssoc の最後のパラメータとして CObject ポインタへの参照を必要とします。したがって、入力時にポインタを CObject 型にキャストする必要があります。次に例を示します。
テンプレートを使用すると、コードがより単純になり、タイプ セーフもさらに確実になります。テンプレートを使用しないコードは、次のように複雑です。
CMapStringToOb myMap; // A nontemplate collection class CPerson myPerson; myMap.SetAt(_T("Bill"), &myPerson); POSITION pos = myMap.GetStartPosition(); while(pos != NULL) { CPerson* pPerson; CString string; // Gets key (string) and value (pPerson) myMap.GetNextAssoc(pos, string, (CObject*&)pPerson); ASSERT(pPerson->IsKindOf( RUNTIME_CLASS(CPerson))); // Use string and pPerson }
詳細については、「CObject コレクションの全オブジェクトの削除」を参照してください。