Frage

ich einen Container von Smart-Pointer auf veränderliche Objekte haben. Ich habe zu schreiben, zwei for_each Induktionsschleifen, ein die Objekte als Nur-Lese-Daten und eine andere für veränderbare Daten für den Zugriff. Der Compiler sagt mir, dass std::vector< boost::shared_ptr<Object> > ist nicht das gleiche wie std::vector< boost::shared_ptr<const Object> >, beachten Sie die const.

Hier ist mein Beispielcode:

#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;
};

Bei all den oben genannten Details, wie implementiere ich die reinen abstrakten Methoden von Record_Base in Record_Derived?

Ich habe versucht:

  • Rückkehr m_fields.begin(), die
    kehrt Konvertierungsfehler (nicht convert std::vector<...> to Field_Iterator)
  • Rückkehr &m_fields[0], das ist gefährlich, weil sie Sachen übernehmen über die Interna von std::vector.

BTW, ich bin mit std::for_each nicht, weil ich über einen Behälter von Feldern Iterierte habe und einen Container von Untersätzen.

War es hilfreich?

Lösung

Was Sie ähnelt tun sowohl die Composite- und Besucher Muster. Diese beiden Muster gut ineinander greifen, so dass es scheint, dass Sie auf dem richtigen Weg sind.

Um die zusammengesetzten Muster zu implementieren, weisen die folgenden Rollen (siehe Kompositum-Muster UML-Diagramm):

  • Leaf -> Field
  • Verbund -> Record
  • Komponente -> Abstrakte Basisklasse von Field und Record (kann nicht denken Sie an einen guten Namen)

Komponenten Operationen, die auf Composite-Typen genannt werden, werden auf rekursiv auf alle Kinder weitergegeben (Blätter und anderer verschachtelter Composite-Typ).

das Besuchermuster zu implementieren, Überlastung operator() in Ihrer Funktor Klasse für jede Komponente Subtyp (Field und Record).

Ich empfehle, dass Sie eine Kopie der erhalten Design Patterns Buch von der „Gang of Four“, die diese Konzepte besser erklärt und viel mehr Details als ich geht in nur kann.

Hier ist ein Beispielcode zu wetzen Ihren Appetit:

#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);
}

Nehmen Sie, möchten Sie vielleicht, Verfahren zur Manipulation / Zugriff auf Kinder, statt der Rückkehr einen Verweis auf die zugrunde liegenden Kinder Vektor.

Andere Tipps

würde ich vorschlagen, keine eigene Iterator zu schreiben, wenn Sie einen gemeinsamen Behältertyp verwenden. einen eigenen Iterator Schreiben macht Sinn, wenn Sie einen eigenen Container schreiben. Wenn Sie jedoch eine benutzerdefinierte schreiben planen Iterator haben einen Blick auf die Boost.Iterator Paket.

Wenn Sie zu verstecken std::vector wollen und seine Iteratoren vom Benutzer, dann müssen Sie polymorphe Iteratoren bieten mit Ihrem polymorphen RecordBase Behälter zu gehen. Schauen Sie sich any_iterator von der Adobe-ASL-Bibliothek. Diese Links auch hilfreich sein kann.

Doch anstatt diese Mühe auf alle gehen, sollten Sie die Composite-und Besucherverhalten in Ihrem Design in Betracht ziehen. Sehen Sie meine andere Antwort.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top