private/public bei vererbtem operator<<
-
Ich bin auf folgendes Problem gestoßen und wäre für Hinweise dankbar:
Ich möchte in einer von ofstream vererbten Klasse alle vererbten Methoden bis auf (alle Überladungen von) operator<< nach außen schützen.
Mein Ansatz ist:
class foo : protected std::ofstream{
public:
using std::ofstream::operator<<;
foo(){...}
};und ich will damit folgendes anwenden können:
foo X;
X << "test" << std:endl;
bar(X); // wobei: void bar(ofstream& ofs);
X.close(); //verbotenMit meinem Ansatz stoße ich auf
»std::basic_ostream<char, std::char_traits<char> >« ist eine nicht erreichbare Basis von »foo«
-
Nun, wie stellst du dir das vor, dass man aus X einen ofstream macht, wenn die ganzen Sachen die einen ofstream auszeichnen, private sind?
Außerdem wird
X<<"test";aus dem gleichen Grund nicht funktionieren, weil dieser Operator eine freie Funktion ist und deswegen nicht mit einem foo benutzt werden kann. Du dürftest stattdessen haufenweise ambigious overloads für die operator<<-Memberfunktionen bekommen.Beschreib mal, was du erreichen willst und warum, dann kann man eine bessere Lösung finden. Willst du die Benutzung von open und close verbieten?
-
SeppJ schrieb:
Nun, wie stellst du dir das vor, dass man aus X einen ofstream macht, wenn die ganzen Sachen die einen ofstream auszeichnen, private sind?
Ja, ich sehe ein, daß das Blödsinn ist.
SeppJ schrieb:
Beschreib mal, was du erreichen willst und warum, dann kann man eine bessere Lösung finden.
Im Grunde möchte ich einen ofstream gegen alle Veränderungen außer durch "<<" schützen.
Momentan übergebe ich den ofstream an mehrere Funktionen, die alle in Wirklichkeit aber nichts anderes als "<<" auf den ofstream machen (sollten).
Dabei hatte sich ein Fehler eingeschlichen, weil eine Funktion ein close() aufgerufen hat. Fehler dieser Art würde ich zukünftig gerne schon vom Compiler ausschließen lassen.SeppJ schrieb:
Willst du die Benutzung von open und close verbieten?
Eigentlich möchte ich alles außer "<<" verbieten.
-
Mach's umgekehrt, verbiete die verbotenen Aktionen:
class foo : public std::ofstream{ public: void close(); }; void bar(std::ofstream& ofs) { } int main() { foo X; X << "Test" <<std::endl; //Funktioniert bar(X); // Funktioniert X.close(); // Fehler }
-
Vielen Dank für deine Antwort.
Ist zwar etwas mühselig, alle Member-Funktionen auf diese Art unbrauchbar zu machen, aber mein Ziel ereiche ich damit tatsächlich.Gibt es einen Grund, warum du
public: void close();statt
private: void close();geschrieben hast?
Das zweite gefiele mir eigentlich besser, da ich dann schon beim Compilieren (und nicht erst beim Linken) einen Fehler beim falschen Aufruf bekomme.
-
thomas___ schrieb:
Das zweite gefiele mir eigentlich besser, da ich dann schon beim Compilieren (und nicht erst beim Linken) einen Fehler beim falschen Aufruf bekomme.
Nein, war nur Unachtsamkeit beim editieren, weil ich die Vorlage von oben bloß ein bisschen angepasst habe.
-
Prima, dann mache ich es so.
Nochmals vielen Dank!
-
Hmmm, leider ist das doch auch nicht ganz das, was ich wollte, weil
X.std::ofstream::close();ja immer noch möglich ist.
Gibt es noch andere Ansätze?
-
thomas___ schrieb:
Hmmm, leider ist das doch auch nicht ganz das, was ich wollte, weil
X.std::ofstream::close();ja immer noch möglich ist.
Gibt es noch andere Ansätze?Dagegen willst Du wirklich schützen? Dein Code ist doch nicht Fort Knox. Außerdem schreibe ich dann
reinterpret_cast<std::ostream*>(&X)->close();//Nimm dies, Pursche!Dagegen kannste pimpln? Nee.
(*reinterpret_cast<std::ostream**>(&X))->close();//Jetzt erst recht, Pursche!
-
Wie wär es wenn deine Wrapperklasse nur das definiert was erlaubt ist.
class Foo { public: Foo() : stream_(/*..*/) { } template<typename T> Foo& in(T t) { stream_ << t; return *this; } Foo& in(std::ostream&(*m)(std::ostream&)) { m(stream_); return *this; } private: std::ostream stream_; }; template<typename T> Foo& operator<<(Foo& f, T t) { return f.in(t); } Foo& operator<<(Foo& f, std::ostream&(*m)(std::ostream&)) { return f.in(m); } template<typename Stream> void bar(Stream& s) { // ... } int main() { Foo f; f << 3 << endl << "hallo"; bar(f); return 0; }Foo ist dabei kein std::ostream, aber ist das denn wirklich gewollt?
-
brotbernd schrieb:
Foo ist dabei kein std::ostream, aber ist das denn wirklich gewollt?
Das wollte ich eigentlich haben, da ich eben schon einige Funktionen der Form
void bar(ostream& s)
habe, an die ich das Objekt übergeben möchte.Trotzdem danke für den Hinweis; ich überlege mir, ob ich die Funktionen evtl. überlade.