2016-06-19 16 views
0

Bear mit mir, ich bin neu in C++. Ich versuche, einen Wert zu aktualisieren, die in einem Vektor gespeichert ist, aber ich bin immer diese Fehlermeldung:Notwendigkeit, Wert von verschachtelter Klasse zu referenzieren und zu aktualisieren C++

non-const lvalue reference to type 'Node' 

Ich bin um std::vector ein einfaches Wrapper so kann ich Methoden teilen wie contains und andere (ähnlich wie die ArrayList in Java ist).

#include <vector> 

using namespace std; 

template <class T> class NewFrames { 

public: 

    // truncated ... 

    bool contains(T data) { 
     for(int i = 0; i < this->vec->size(); i++) { 
      if(this->vec->at(i) == data) { 
       return true; 
      } 
     } 

     return false; 
    } 

    int indexOf(T data) { 
     for(int i = 0; i < this->vec->size(); i++) { 
      if(this->vec->at(i) == data) { 
       return i; 
      } 
     } 

     return -1; 
    } 

    T get(int index) { 
     if(index > this->vec->size()) { 
      throw std::out_of_range("Cannot get index that exceeds the capacity"); 
     } 

     return this->vec->at(index); 
    } 

private: 
    vector<T> *vec; 

}; 

#endif // A2_NEWFRAMES_H 

Die Klasse, die diese Umhüllung verwendet, ist wie folgt definiert:

#include "Page.h" 
#include "NewFrames.h" 

class Algo { 

private: 
    typedef struct Node { 
     unsigned reference:1; 
     int data; 
     unsigned long _time; 

     Node() { } 

     Node(int data) { 
      this->data = data; 
      this->reference = 0; 
      this->_time = (unsigned long) time(NULL); 
     } 
    } Node; 

    unsigned _faults; 
    Page page; 
    NewFrames<Node> *frames; 
}; 

I an einem Punkt, wo bin ich brauche innerhalb des Vektors eine der Node Objekte zu verweisen, aber ich brauche in der Lage sein, reference auf einen anderen Wert zu ändern. Von dem, was ich auf SO gefunden habe, muss ich dies tun:

const Node &n = this->frames->get(this->frames->indexOf(data)); 

Ich habe versucht, nur mit:

Node n = this->frames->get(this->frames->indexOf(data)); 
n.reference = 1; 

und dann die Daten im Debugger sehen, aber der Wert ist nicht aktualisiert, wenn ich später überprüfe. Bedenken Sie:

const int data = this->page.pages[i]; 
const bool contains = this->frames->contains(Node(data)); 
Node node = this->frames->get(index); 
for(unsigned i = 0; i < this->page.pages.size(); i++) { 
    if(node == NULL && !contains) { 
     // add node 
    } else if(contains) { 
     Node n = this->frames->get(this->frames->indexOf(data)); 
     if(n.reference == 0) { 
      n.reference = 1; 
     } else { 
      n.reference = 0; 
     } 
    } else { 
     // do other stuff 
    } 
} 

Bei nachfolgenden Durchläufen der Schleife, wird der Knoten mit dem bestimmten Datenwert irgendwie anders ist. Wenn ich versuche, n.reference zu ändern, erhalte ich einen Fehler, weil const das Objekt daran hindert, sich zu ändern. Gibt es eine Möglichkeit, wie ich diesen Knoten bekommen kann, damit ich ihn ändern kann? Ich komme aus der freundlichen Java-Welt, in der so etwas funktionieren würde, aber ich möchte wissen/verstehen, warum das nicht in C++ funktioniert.

+0

Dies ist nicht das Problem, aber Namen, die zwei aufeinanderfolgende Unterstriche enthalten ('__A2_NEWFRAMES_H__') und Namen, die mit einem Unterstrich gefolgt von einem Großbuchstaben beginnen, sind für die Implementierung reserviert. Benutze sie nicht. –

+0

Sie sollten 'vector * vec;' durch 'vector vec;' ersetzen, um unnötige manuelle Speicherverwaltung zu vermeiden. – nwp

+0

Seufzer. Zerhacken Sie den Code, bis Sie das kleinste Stück Code erhalten, das Sie erstellen können, das das Problem anzeigt. Niemand wird durch all diese irrelevanten Sachen waten, um herauszufinden, was los ist. –

Antwort

0
Node n = this->frames->get(this->frames->indexOf(data)); 
n.reference = 1; 

Dies kopiert die Node von frames und speichert die kopieren als Objekt n. Das Ändern der Kopie ändert den ursprünglichen Knoten nicht.

Die einfachste "Lösung" ist die Verwendung einer Referenz. Das bedeutet, dass die Änderung der Rückgabetyp get von T zu T& und Ändern der vorherigen zwei Zeilen

Node& n = this->frames->get(this->frames->indexOf(data)); 
n.reference = 1; 

, dass der Code erhalten sollte zu arbeiten. Aber es gibt so viele Indizien im Code, dass es wahrscheinlich noch andere Probleme gibt, die noch nicht aufgetaucht sind. Wie @nwp in einem Kommentar sagte, wird die Verwendung von vector<T> anstelle von vector<T>* Ihnen viele Kopfschmerzen ersparen.

Und während ich Stilberatung geben, loswerden diese this-> s; Sie sind nur Lärm. Und vereinfachen Sie die Gültigkeitsprüfung für Gürtel und Hosenträger: Wenn Sie von 0 zu vec.size() loopen, müssen Sie beim Zugriff auf das Element nicht überprüfen, ob der Index in Ordnung ist. Ändern Sie vec.at(i) zu vec[i]. Und in get, beachten Sie, dass vec.at(index) eine Ausnahme auslösen wird, wenn index außerhalb der Grenzen ist, so können Sie entweder die anfängliche Bereichsüberprüfung überspringen oder halten Sie die Überprüfung (nach der Korrektur, so dass es den tatsächlichen Bereich überprüft) und wieder vec[index] stattdessen verwenden von vec.at(index).