これを正しく行うのは難しいでしょう。
begin()とend()の署名はどうあるべきですか?
多くの選択肢はありません、彼らはほとんど次のようなものでなければなりません
RuleBook::iterator begin();
RuleBook::iterator end();
const
(必要に応じてオーバーロードを追加します)
BasketballRulesとCompanyRulesはどのように実装する必要がありますか?
気をつけて :)
イテレータが最後の項目を通過したときの終了条件をどのように処理しますか?
イテレータタイプを正しく設計して、正しく機能するようにします。等しいかどうかを比較でき、インクリメントできるイテレータタイプが必要です。コンテナ内の最後のアイテムへのイテレータがあり、それをインクリメントする場合、それは過去のイテレータと等しくなる必要があります。
Rule *をイテレーターとして使用し、null_ptrをエンドポイントを超えて使用してすべてを実装する場合、これはSTLに準拠しますか?
いいえ。イテレータタイプがちょうどそのときイテレータRule*
をインクリメントしても次の場所に移動しない場合はRule
、メモリ内の次の場所を指しているだけであり、オブジェクトでさえない可能性があり、Rule
未定義の動作につながります。たとえば、ポイントしているときにそれをインクリメントするBasketballRules
場合、有効なオブジェクトをポイントしていません。つまり、aによって占有されているメモリをポイントしており、それを逆参照することは未定義の動作です。Rule*
m_r
Rule
m_rp
Rule*
また、aをインクリメントし続けるとRule*
、過去の値に到達することはありませんnullptr
。
もっともらしい実装であるため、私はYakkの回答に賛成票を投じましたが、正しく理解するのは難しいでしょう。考慮し、ポリモーフィックインターフェイスに含めることはたくさんあります。たとえば、1つがaを指し、もう1つがaを指す2つのオブジェクト==
を比較するために使用するとどうなりますか?ポリモーフィックイテレータの等式はどのように機能しますか?RuleBook::iterator
CompanyRules
BasketballRules
BasketballRules
イテレータをオブジェクトに、イテレータをオブジェクトに割り当てるとどうなりCompanyRules
ますか?ポリモーフィックタイプには「ディープコピー」が必要です。
コンテナごとに異なる派生イテレータ-implタイプが必要です。コンテナのイテレータタイプは、派生コンテナタイプごとにタイプCompanyRule
に関するすべてを知っている必要があります。CompanyRule
これらの具体的なイテレータ-implタイプのそれぞれは、仮想関数としてイテレータインターフェイスのほぼ全体を実装する必要があります。実装の難しさは、設計に問題があることを示しています。
より単純な設計は、派生したコンテナタイプごとに、同じタイプの実際の物理コンテナを管理することです。各派生コンテナに固有のコードは、派生オブジェクトのコンテンツが変更されるたびにリストのコンテンツを更新するだけで構成されています。その場合、イテレータタイプは単純で、非多型です。
struct RuleBook
{
typedef std::vector<Rule*> list_type;
typedef list_type::iterator iterator;
virtual iterator begin() = 0;
virtual iterator end() = 0;
};
struct CompanyRules :
public RuleBook
{
CompanyRules() : m_list{ &m_r } { }
Rule m_r;
iterator begin() { return m_list.begin(); }
iterator end() { return m_list.end(); }
private:
list_type m_list;
};
struct BasketballRules :
public RuleBook
{
BaseketballRules() : m_list{ &m_r, m_rp, *m_rpp } { }
// return the three Rules, one-at-a-time, in succession
Rule m_r;
Rule* m_rp;
Rule** m_rpp;
iterator begin() { return m_list.begin(); }
iterator end() { return m_list.end(); }
private:
// N.B.
// must update m_list[1] any time m_rp changes
// must update m_list[2] any time the pointee of m_rpp changes (harder!)
list_type m_list;
};