2016-05-18 2 views
1

Ich versuche die Depth First Search als eine Funktion zu implementieren, die ein Diagramm aufnimmt und das DFS ausgibt.Wie kann ich legal auf die privaten Felder Vektor und Karte zugreifen und diese ändern, ohne die Kapselung zu verletzen?

Oben ist die Klasse, die ich für den Graph gemacht habe. Ich versuche, eine Funktion zu machen, die den Zeiger auf den privaten Vektor und die Karte zurückgibt, damit ich für Schleife Operationen auf der Adjazenzliste und den Map-Datenstrukturen des Graphen ausführen kann. Ich weiß jedoch, dass die Manipulation der Datenstrukturen direkt eine Verletzung der Kapselung ist und ich wollte die objektorientierte Disziplin meines Programms beibehalten. Wie ist dies ohne Verletzung der Kapselung möglich?

PS: Ich freue mich nicht auf die Verwendung von Freund-Funktion, da ich nicht die Funktion eine Ausnahme machen möchte. Ich möchte eine Mainstream-Lösung finden, die von Programmierern gerne genutzt wird und eine disziplinierte Lösung darstellt. Ich kann jedoch meine Klassenfelder/Zugänglichkeit bei Bedarf ändern.

Vielen Dank für Ihre Zeit!

+0

Kann Haben Sie eine 'public' Funktion, die eine Kopie von' map' und 'vector' zurückgibt? Vorausgesetzt, die Anrufer müssen keine Elemente ändern, sollte dies kein Problem darstellen. – Tas

+0

Sie können (const) Iteratoren an die 'begin()' und 'end()' jeder Sequenz zurückgeben, was das Iterieren, aber nicht das Einfügen oder Löschen ermöglicht. Leider bietet das keine Suche nach der 'std :: map'. –

+0

Die Anrufer müssen Elemente ändern. –

Antwort

0

Wenn Sie einen Iterator über die Adjazenzkarte ausführen müssen, fügen Sie eine Memberfunktion hinzu, mit der Sie dies tun können.

Sie haben zwei offensichtliche Möglichkeiten:

  1. Ihre eigene AdjacencyMapIterator Klasse definieren und begin()/end(), die Instanzen von denen Rückkehr.
  2. Stellen Sie eine Funktion zur Verfügung, die einen Funktor enthält, wobei der Funktor bei jedem Eintrag in der Adjazenzkarte aufgerufen wird.

Die erste würde wie folgt aussehen:

for(auto it = graph.adjacency_begin() ; it!=graph.adjacency_end(); ++it) { 
    vertex& v1 = it->v1; 
    vertex& v2 = it->v2; 
    ... 
} 

Die zweite würde aussehen wie

graph.for_each_adjacency(
    [](vertex& v1, vertex &v2) { .... } 
); 

Das größte Problem heraus arbeitet, wie Änderungen an der Graphenstruktur während der Iteration zu handhaben. Die meisten Implementierungen, die ich gesehen habe, schließen dies explizit aus (entweder indem sie eine Ausnahme auslösen oder angeben, dass dies ein undefiniertes Verhalten ist) oder die Iteration für eine interne Kopie ausführen. Wenn Sie etwas anderes brauchen - erwarten Sie, dass es in Zukunft ein Problem ist.

, wenn Sie einige Updates in einer Schleife tun wollen, wo innerhalb der Schleife Aktualisierung ist nicht nur Schleife das erfordert Updates irgendwo zu speichern erlaubt, dann alle Updates anwenden, nachdem die Schleife beendet ist:

Sie
std::vector<UpdateInfo> updates; 
graph.for_each_adjacency([&updates](const vertex& v1, const vertex& v2) { 
    updates.push_back(calculateUpdate(v1,v2)); 
}); 

foreach(updates, [&graph](const UdpateInfo &update) { 
    applyUpdate(update, graph); 
}); 
1

Sie sollten entscheiden, ob Sie "objektorientiert" sind oder nicht. Wenn nicht, dann hast du gerade eine Struktur (aka record), also mach deine Felder öffentlich und mach Party. Aber wenn Sie O-O sind, dann gibt es ein paar Wege zu gehen. Sie könnten Zugriffsmethoden auf Graph bereitstellen, die z. B. eine, die einen Eckpunkt gibt, Kanten (oder benachbarte Eckpunkte) zurückgibt. Dann schreiben Sie Ihren Traversal-Algorithmus außerhalb des Graphen. Alternativ stellen Sie Ihren Traversal-Algorithmus als eine Methode von Graph zur Verfügung und es hat direkten Zugriff auf die privaten Mitglieder.

+0

Ja das ist, was ich tat (Sie stellen Ihren Traversal-Algorithmus als eine Methode von Graph zur Verfügung und es hat direkten Zugang zu den privaten Mitgliedern), aber ich hatte das ängstliche Gefühl, dass es nicht richtig war. Fragst du nur, dass irgend etwas rechtlich falsch ist? Verstößt es OOP überhaupt? –

+0

@DanishAmjadAlvi Nein, es ist definitiv O-O. Sehr oft finden Sie Algorithmen innerhalb der Klasse, besonders dort, wo sie eng gekoppelt werden müssen. In einigen Fällen ist es jedoch vorteilhaft, sie getrennt zu halten. Nehmen wir beispielsweise an, Sie wollten mehrere Algorithmen kodieren - Traversierungen, maximale Verbindungen, usw. _Nehmen Sie an, Sie wollten verschiedene _Vorstellungen_ haben - zB haben Sie derzeit eine Adjazenzliste, aber Sie möchten vielleicht - aus verschiedenen Gründen, in anderen Fällen - Adjazenzmatrix, Inzidenzmatrix oder etwas anderes. Vielleicht möchten Sie dann Ihre Algorithmen trennen. – davidbak

Verwandte Themen