コレクションの全メンバーへのアクセス
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
メンバー関数を使用します。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
へのポインターにキャストする必要があります。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 コレクションの全オブジェクトの削除」を参照してください。