コレクションの全メンバーへのアクセス
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 コレクションの全オブジェクトの削除」を参照してください。