2 Themen: Benutzung von Templateparametern, Verständnis von 'private'
-
Hallo liebe Community,
In Stroustrup wird eine Template-Klasse so definiert:
template<class C> class String{ ...Wenn ein Template-Element außerhalb der der Template-Klasse definiert wird sieht der Code im Buch so aus:
template<class C> struct String<C>::Srep{ ...Meine Frage ist nun, warum bei der Definition des Elements nach dem Klassennamen 'String' der Templateparameter noch in spitzen Klammern stehen muß während oben bei der Definition der Klasse dies nicht nötig ist (was auch nachvollziehbar ist, da vor dem Namen der Template-Parameter bereits angegeben ist und somit feststeht.
Zur 2ten Frage:
In effektiv Programmieren von Scott Meyers wird std::swap für eine eigene Klasse angepaßt, indem sie spezialisiert wird:
namespace std{ template<> void swap<Widget>(Widget& a, Widget& b) { swap(a.pImpl, b.pImpl); } }pImpl ist ein privater Zeiger innerhalb von Widget und darf nicht außerhalb der Klasse zugegriffen werden und im Buch steht auch entsprechend, daß dieser Code so nicht kompiliert wird. Alles schön und gut und richtig und die Lösung im Buch sagt, daß man in Widget eine öffentliche Elementfunktion namens swap deklarieren kann, die den tatsächlichen Tausch vollzieht, und man dann die std::swap-Version dahingehend spezialisiert, dass sie die Elementfunktion aufruft:
class Widget{ public: ... void swap(Widget& other) { using std::swap; swap(pImpl, other.pImpl); } ... } namespace std{ template<> void swap<Widget>(Widget& a, Widget& b) { a.swap(b); } }Um also die Spezialisierung richtig durchführen zu können ruft die swap-Spezialisierung ihre nichtspezialisierte Version über eine öffentliche Funktion in Widget auf, sehe ich das richtig? Das ist auch noch nicht mein Problem. Mein Problem ist die Zeile wo die öffentliche swap-Funktion von Widget die nicht spezialisierte std::swap-Funktion aufruft.In dieser Zeile wird auf den pImpl-Zeiger von other zugegriffen und dies soll in Ordnung sein, womit ich meine Probleme habe, denn auch wenn innerhalb einer Elementfunktion von Widget eine Widget-Instanz auf die private-Elemente einer anderen Instanz zugreift, bleiben diese Elemente der anderen Instanz nun mal "fremd" und nicht eigen und damit dürfte der Zugriff durch other.pImpl weiterhin nicht funktionieren, weil dieses Zeiger-Element nun mal einer anderen Instanz gehört.
Der obige Code würde doch bedeuten, daß zwischen verschiedenen Klassen nicht auf private-Elemente zugegriffen werden kann aber auf der anderen Seite zwischen Objekten der selben Klasse völlige Anarchie herrschen würde. Ich hätte gedacht, daß man auch hier immernoch eine zusätzliche Elementfunktion benötigt hätte auf die die nichtspezialisierte swap-Funktion zugreifen kann, wie z.B.:
swap(pImpl, other.getpImpl())Somit würde Widget seinen Zeiger öffentlich zur Verfügung stellen, dies wäre für mich die einzige Möglichkeit.
Wahrscheinlich habe ich die Philosophie vom kleinen Wörtchen "private" noch nicht ganz verstanden, weswegen auch diese Frage eine Verständnisfrage ist und keine Kritik am Code in diesem Buchs
.vielen Dank im voraus
-
Habe ich dich richtig verstanden, dass deine Frage einfach nur ist warum folgendes keinen Fehler gibt?
class Foo { private: Bar b; public: Foo(const Foo& f) { b = f.b; } };Dann hast du tatsächlich die Bedeutung von private missverstanden. Auf private deklarierte Methoden und Attribute kann nur innerhalb der Klasse zugegriffen werden, d.h. auf private Attribute von Foo nur innerhalb von Foo. Das heißt aber nicht, dass nur auf die von "this" zugegriffen werden kann, sondern auch auf die anderer Foo-Objekte, die bspw. als Parameter übergeben werden, denn man befindet sich ja schließlich immer noch in der Klasse Foo.
-
Jupp OhneName,
das ist genau die Antwort meiner Frage,
vielen Dank, dann erübrigt sich der Zusatz den ich nachträglich hinzugefügt habe ja vollständig :), kannst du mich auch in der ersten Frage erhellen?