0

可変オブジェクトへのスマートポインターのコンテナーがあります。2つのfor_eachループを作成する必要があります。1つは読み取り専用データとしてオブジェクトにアクセスするためのもので、もう1つは可変データ用です。std::vector< boost::shared_ptr<Object> >コンパイラは、と同じではないと言っています。std::vector< boost::shared_ptr<const Object> >に注意してくださいconst

これが私のサンプルコードです:

#include <vector>
#include "boost/shared_ptr.hpp"
#include <iterator>

class Field_Interface
{ ; };
typedef boost::shared_ptr<Field_Interface> Ptr_Field_Interface;
typedef boost::shared_ptr<const Field_Interface> Ptr_Const_Field_Interface;

struct Field_Iterator
  : std::input_iterator<std::forward_iterator_tag, Ptr_Field_Interface>
{
  // forward iterator methods & operators...
};

struct Const_Field_Iterator
  : std::input_iterator<std::forward_iterator_tag, Ptr_Const_Field_Interface>
{
  // forward iterator methods & operators...
};

struct Field_Functor
{
  virtual void operator()(const Ptr_Field_Interface&) = 0;
  virtual void operator()(const Ptr_Const_Field_Interface&) = 0;
};

class Record;
typedef boost::shared_ptr<Record> Ptr_Record;
typedef boost::shared_ptr<const Record> Ptr_Const_Record;

class Record_Base
{
  protected:
    virtual Field_Iterator beginning_field(void) = 0;
    virtual Field_Iterator ending_field(void) = 0;
    virtual Const_Field_Iterator const_beginning_field(void) = 0;
    virtual Const_Field_Iterator const_ending_field(void) = 0;

    void for_each(Field_Functor * p_functor)
    {
       Field_Iterator iter_begin(beginning_field());
       Field_Iterator iter_end(ending_field());
       for (; iter_begin != iter_end; ++ iter_begin)
       {
         (*p_functor)(*iter_begin);
       }
     }
};

class Record_Derived
{
public:
   typedef std::vector<Ptr_Field_Interface> Field_Container;
   typedef std::vector<Ptr_Record>          Record_Container;
private:
   Field_Container m_fields;
   Record_Container m_subrecords;
};

Record_Base上記のすべての詳細を考えると、 inの純粋な抽象メソッドを実装するにはどうすればよいRecord_Derivedですか?

私はもう試した:

  • を返します。これ は変換エラーを返します(変換できませm_fields.begin()ん)
    std::vector<...> to Field_Iterator
  • を返す&m_fields[0]。これは、の内部に関するものを想定しているため、危険ですstd::vector

ところで、std::for_eachフィールドのコンテナとサブレコードのコンテナを反復処理する必要があるため、使用していません。

4

3 に答える 3

1

あなたがしていることは、コンポジットパターンとビジターパターンの両方に似ています。これらの2つのパターンはうまくかみ合っているので、正しい方向に進んでいるようです。

複合パターンを実装するには、次の役割を割り当てます(複合パターンUML図を参照)。

  • 葉->Field
  • コンポジット->Record
  • Fieldコンポーネント-> andの抽象基本クラスRecord(良い名前は思いつかない)

複合型で呼び出されるコンポーネント操作は、すべての子(リーフおよびその他のネストされた複合型)に再帰的に渡されます。

ビジターパターンを実装するには、operator()各コンポーネントサブタイプ(フィールドとレコード)のファンクタークラスをオーバーロードします。

「GangofFour」のデザインパターンの本を入手することをお勧めします。この本は、これらの概念をよりよく説明し、私ができるよりもはるかに詳細に説明しています。

食欲をそそるサンプルコードは次のとおりです。

#include <iostream>
#include <vector>
#include "boost/shared_ptr.hpp"
#include "boost/foreach.hpp"

class Field;
class Record;

struct Visitor
{
    virtual void operator()(Field& field) = 0;
    virtual void operator()(Record& field) = 0;
};

class Component
{
public:
    virtual bool isLeaf() const {return true;}
    virtual void accept(Visitor& visitor) = 0;
};
typedef boost::shared_ptr<Component> ComponentPtr;

class Field : public Component
{
public:
    explicit Field(int value) : value_(value) {}
    void accept(Visitor& visitor) {visitor(*this);}
    int value() const {return value_;}

private:
    int value_;
};

class Record : public Component
{
public:
    typedef std::vector<ComponentPtr> Children;
    Record(int id) : id_(id) {}
    int id() const {return id_;}
    Children& children() {return children_;}
    const Children& children() const {return children_;}
    bool isLeaf() const {return false;}
    void accept(Visitor& visitor)
    {
        visitor(*this);
        BOOST_FOREACH(ComponentPtr& child, children_)
        {
            child->accept(visitor);
        }
    }

private:
    int id_;
    Children children_;
};
typedef boost::shared_ptr<Record> RecordPtr;

struct OStreamVisitor : public Visitor
{
    OStreamVisitor(std::ostream& out) : out_(out) {}
    void operator()(Field& field) {out_ << "field(" << field.value() << ") ";}
    void operator()(Record& rec) {out_ << "rec(" << rec.id() << ") ";}
    std::ostream& out_;
};

int main()
{
    RecordPtr rec(new Record(2));
        rec->children().push_back(ComponentPtr(new Field(201)));
        rec->children().push_back(ComponentPtr(new Field(202)));
    RecordPtr root(new Record(1));
        root->children().push_back(ComponentPtr(new Field(101)));
        root->children().push_back(rec);

    OStreamVisitor visitor(std::cout);
    root->accept(visitor);
}

Recordでは、基になる子ベクトルへの参照を返す代わりに、子を操作/アクセスするためのメソッドを提供することができます。

于 2010-02-13T04:36:16.597 に答える
0

一般的なコンテナタイプを使用する場合は、独自のイテレータを作成しないことをお勧めします。独自のイテレータを作成することは、独自のコンテナを作成するときに意味があります。ただし、カスタムイテレータを作成する場合は、Boost.Iteratorパッケージを参照してください。

于 2010-02-13T00:50:12.127 に答える
0

とそのイテレータをユーザーから非表示にする場合は、ポリモーフィックコンテナstd::vectorと一緒に使用するポリモーフィックイテレータを提供する必要があります。AdobeASLライブラリからRecordBaseチェックアウトしてください。これらのリンクも役立つ場合があります。any_iterator

ただし、そのような問題をすべて解決するのではなく、デザインでコンポジットパターンとビジターパターンを使用することを検討する必要があります。私の他の答えを参照してください。

于 2010-02-13T04:15:40.000 に答える