2011-01-15 9 views
0


Mehr oder weniger alles ist im Thema.
wenn ichBenutzerdefinierter Container mit benutzerdefiniertem Iterator funktioniert nicht, wenn Container als const definiert ist

func(my_cont& c) 
{ c.begin() }; 

Sachen funktioniert, aber

func(const my_cont& c) 
{ c.begin() }; 

nicht funktioniert, Compiler behauptet, dass < ..> .... von my_cont < zu konst my_cont wandeln diese kippe .. >

Was sind die Anforderungen für den Container und meinen benutzerdefinierten Iterator, um damit umzugehen?

+1

Haben Sie eine 'const'-Version von' begin() ', die einen Iterator zurückgibt, der mit' const' container arbeitet? –

Antwort

4

Ihre Container-Klasse sollte zwei Implementierungen von begin() und end() hat - eine Rückkehr Iterator und eine andere Rückkehr const_iterator:

 iterator begin(); 
const_iterator begin() const; 
     iterator end(); 
const_iterator end() const; 

const_iterator nicht verwendet werden kann, um das Objekt zu verändern, dass es zu den Punkten.

1

Sie benötigen einen const begin(), so etwas fügen:

class my_cont 
{ 
public: 
    const_iterator begin() const; 
}; 

Sie finden auch eine const_iterator Typ definieren.

0

Dies ist genau der Grund, warum STL cost_iterator für Container implementiert. Überprüfen Sie einfach, wie es in STL implementiert ist, ich bin mir nicht sicher, ob Sie eine bessere Lösung finden können.

0

Sie können const Member-Funktionen nur für ein const-Objekt (oder flüchtige Member-Funktionen für ein flüchtiges Objekt) aufrufen. Der Compiler sagt, dass iterator my_cont::begin() const fehlt.

+0

'iterator my_cont :: begin() const' ist nicht in der gleichen Weise wie' int * pr' nicht in 'pr = & r' für' const int r' verwendbar. Benötigt wird der Rückgabewert "const_iterator" (für zukünftige Operationen) und nicht nur "const" der Methode 'my_cont :: begin()' selbst. –

1

Hier ist ein guter Artikel über das Schreiben Iteratoren:
http://www.aristeia.com/Papers/CUJ_June_2001.pdf

Da die meisten Menschen haben festgestellt, benötigen Sie eine const-Version von begin() und end(), dass ein const_iterator zurückgibt.

Was die meisten Leute vergessen haben ist, dass ein Iterator implizit in einen Const_iterator konvertiert werden kann. Sonst ist es schwierig, einen Const-Iterator von einem Nicht-Kosten-Objekt zu erhalten (ohne viele böse Umwandlungen).

my_cont data; 
for(my_cont::const_iterator loop = data.begin(); loop != data.end(); ++loop) 
{ 
    /* STUFF */ 
} 

Hinweis oben: Die oben genannten Aufrufe werden tatsächlich die nicht kostenpflichtigen Versionen begin() und end() aufrufen. Aber sie werden einem const_iterator zugewiesen. Also müssen Ihre Iteratoren in const_iterator konvertiert werden, damit der obige Code funktioniert (Hinweis: Es gibt keine implizite Konvertierung von const_iterator in iterator. Das sollte eine explizite const_cast annehmen, da sie von Natur aus gefährlich ist).

class my_cont 
{ 
    public: 
    class iterator { /* STUFF */ } 
    class const_iterator 
    { 
     public: const_iterator(iterator const& rhs); 
     /* STUFF */ 
    } 

    iterator  begin(); 
    iterator  end(); 

    const_iterator begin() const; 
    const_iterator end() const; 
    /* STUFF*/ 
}; 
+0

Tiefste Antwort hier. Vielen Dank.Aus dem verlinkten Artikel von Meyers: "Der Grund, warum der Cast nicht kompiliert wird, ist, dass' iterator' und 'const_iterator' für diese Containertypen völlig unterschiedliche Klassen sind, die kaum enger miteinander verwandt sind als' string' und 'complex '." –

Verwandte Themen