Kann ich einen vector::iterator in einen anderen konvertieren?



  • A object;
    
    std::vector<A*>::iterator it =
    static_cast<std::vector<B*>::iterator>(object->GetChildList()->begin());
    
    error C2440: 'static_cast': 'std::_Vector_iterator<_Ty,_Alloc>' kann nicht in 'std::_Vector_iterator<_Ty,_Alloc>' konvertiert werden
    

    Ist das realisierbar?

    Ein einzelnes Objekt aus der Liste umkonvertieren geht, aber beim Iterator kommt immer der o.g. Fehler.

    Gruß



  • Was hast du vor? Wozu meinst du nen iterator casten zu müssen?



  • Ich habe in einer Liste viele Objekte gespeichert die von der selben Basisklasse abgeleitet sind.

    Nun möchte irgendwo im Programm einen Iterator vom gewünschten Typ holen, um damit zu arbeiten.

    Ich habe eine funktioniernde Methode, um die Objekte zu casten, aber ein Iterator wäre ganz nett.



  • Nochmals, wieso brauchst du einen Iterator, der auf einen anderen Elementtyp zeigt als der Elementtyp des Container? Um anders darauf zuzugreifen?

    Wieso überhaupt casten? Geht es um Zeiger (Polymorphie)? Wäre es da nicht besser, du würdest mit virtuellen Funktionen arbeiten?

    Etwas genauere Informationen wären schon noch hilfreich...



  • Hi,

    also sehr wahrscheinlich bin ich auf dem falschen Dampfer:

    Die abgeleiteten Objekte besitzen Eigenschaften, die in der Basisklasse nicht vorkommen.

    Ich kann über den Iterator mit dem Typen des Containers nicht auf diese Eigenschaften zugreifen.

    Der Grund, weshalb ich das einbauen möchte ist, dass ich mit einem Kurs an der Uni ein Spiel programmiere und eine Person unbedingt einen Iterator will, um die Liste der Spielobjekte zu durchlaufen (um einen fertigen Code einzubauen :()

    edit: ich hab der Person nun empfohlen, eine seperate Liste zu führen, da ich es leid war 😋



  • In den Containern sind doch Zeiger. Dann musst du doch nicht den Iterator casten, sondern das Object auf das der Iterator zeigt. Das ist problemlos möglich.



  • Braunstein schrieb:

    In den Containern sind doch Zeiger. Dann musst du doch nicht den Iterator casten, sondern das Object auf das der Iterator zeigt. Das ist problemlos möglich.

    Ich glaube, er wollte ohne zusätzlichen Aufwand normal über den Container iterieren, sodass er jeweils gecastete Elemente erhält.

    Hier mal ein kleiner Vorschlag. Ich habe den nativen Iterator gewrappt und durch einen ersetzt, der bei der Dereferenzierung automatisch castet. Du solltest dich allerdings mit Templates und Klassen gut auskennen, sonst wirst du Verständnisprobleme haben.

    template <typename DestT, typename SourceT>
    class cast_iterator
    {
    	private:
    		typedef typename std::vector<SourceT*>::iterator iter_t;
    		typedef cast_iterator<DestT,SourceT> cast_iter_t;
    
    	public:
    		cast_iterator(iter_t iter)
    		: m_iter(iter)
    		{
    		}
    
    		cast_iter_t& operator++()
    		{
    			++m_iter;
    			return *this;
    		}
    
    		DestT& operator*()
    		{
    			return *static_cast<DestT*>(*m_iter);
    		}
    
    		DestT* operator->()
    		{
    			return static_cast<DestT*>(*m_iter.operator->());
    		}
    
    		friend bool operator!= (const cast_iter_t& lhs, const cast_iter_t& rhs)
    		{
    			return lhs.m_iter != rhs.m_iter;
    		}
    
    	private:
    		iter_t m_iter;
    };
    

    Anwendung:

    struct A
    {
        void func();
    };
    
    struct B : public A
    {
        void func();
    };
    
    int main()
    {
        std::vector<A*> v; // mit Zeigern auf B-Objekte füllen
        for (cast_iterator<B, A> i = v.begin(); i != v.end(); ++i)
        {
        	i->func(); // ruft B::func auf
             B& b = *i; // Referenz auf B-Objekt
        }
    }
    

    Natürlich musst du hier noch einiges erweitern, um z.B. mit const_iterator kompatibel zu sein. Viele Operatoren fehlen zudem noch. Ich habe mein Beispiel auf std::vector beschränkt, mit zusätzlichen Templateparametern könnte man auch das verallgemeinern. Mein Code sollte nur mal als Anregung dienen, falls du interessiert bist und dich auch mit Theorie beschäftigst, sollte der Rest kein Problem sein. 😉



  • Hey super, Nexus!

    Danke dir vielmals für deine Mühen.

    Template Funktionen sind mir vertraut, aber ich muss mir deinen Code nochmal genauer ansehen, um alles zu verstehen 😉

    Gruß



  • Kein Problem. 😉

    Ich hoffe, das hilft dir ein wenig, stelle bei Bedarf einfach wieder Fragen (zum Beispiel, wenn dir Teile meines Codes nicht ganz einleuchten).

    Die friend -Funktionsdefinition mag dir vielleicht nicht ganz vertraut sein, ich hab das der Einfachheit halber so gelöst. Das kommt einer globalen Funktion (bzw. einem Funktionstemplate) gleich, die ein friend der Klasse ist und somit auf die Member zugreifen darf.

    Falls du die Operatorüberladung nicht ganz nachvollziehen kannst, gibts einen sehr schönen Artikel von pumuckl. Gerade operator-> ist etwas speziell, wenn man ihn das erste Mal sieht.


Anmelden zum Antworten