コレクションの全メンバーへのアクセス
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要素にアクセスできます。CTypedPtrArray上記のforループ本体のステートメントは、次のように書き換えることができます。CPerson *thePerson = myArray[i];この演算子は、 と 以外
constのバージョンの両方constに存在します。 配列constに対して呼び出されるバージョンconstは、代入ステートメントの右側にのみ表示できます。
リストを反復処理するには
リスト内の項目を順に処理するには、
GetHeadPositionメンバー関数とGetNextメンバー関数を使用します。CTypedPtrList<CObList, CPerson *> myList; myList.AddHead(new CPerson()); POSITION pos = myList.GetHeadPosition(); while (pos != NULL) { CPerson *thePerson = myList.GetNext(pos); thePerson->AssertValid(); }この例では、型付きポインター リストを使用して、
CPersonオブジェクトへのポインターを格納します。 リストの宣言は、「 配列を反復処理するには 」の配列に対する宣言に似ていますが、 クラスから派生しています。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へのポインターにキャストする必要があります。Note
非テンプレート マップの場合、コンパイラには、
CObjectの最後のパラメーターとしてGetNextAssocポインターへの参照が必要です。 入力時には、ポインターをその型にキャストする必要があります。次に例を示します。テンプレートを使用すると、よりシンプルなソリューションが実現し、タイプ セーフもさらに確実になります。 テンプレートを使用しないコードは、次のようにより複雑になります。
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 コレクションの全オブジェクトの削除」を参照してください。