Member von Basisklasse verstecken
-
Hallo Leute ich hab mal ne Frage zur Vererbung:
Also ich habe eine Basisklasse mit einer privaten Instanzvariable die ich über Get() und Set() Funktionen ändern lasse.
Jetzt habe ich allerdings eine Klasse die von dieser Basisklasse abgeleitet ist, und in der diese Funktionen nichtmehr zur Verfügung stehen sollen.
Wie realisiere ich das?
thx für die antworten
-
Klingt nach schrägem Design, wie sieht denn die Klassenstruktur aus?
-
.filmor schrieb:
Klingt nach schrägem Design, wie sieht denn die Klassenstruktur aus?
ein beispiel (das is natürlich vereinfacht):
class Window { private: basic_string<TCHAR> name; public: basic_string<TCHAR> GetName() { return name; } void SetName(basic_string<TCHAR> neu) { name = neu; } }; class Button : Window { //hier soll name fix mit "Button" belegt sein und nicht mehr änderbar };jetzt kommt mir bloß nicht mit dem WinAPI-Forum, das ist ein c++ Problem

und thx für die schnelle antwort
-
Dann solltest Du den Namen am Besten per Konstruktor an die Basisklasse übergeben und garkeinen Setter anbieten...
-
Ein Button ist kein Window und er ist auch nicht mit Window implementiert. Woher kommt also die Vererbungsbeziehung?
Warum soll der Name überhaupt während der Laufzeit änderbar sein? Wenn du ihn einfach als const basic_string<TCHAR> über den Konstruktor initialisierst hast du das Problem nicht. (Übrigens, getter-Methoden sind immer const und liefern eine Referenz auf ein konstantes Objekt zurück.)
-
class Button : Window { public: basic_string<TCHAR> GetName() { return "Button"; } void SetName(basic_string<TCHAR> neu) { } };Ganz einfach.

-
Ein Button ist kein Window und er ist auch nicht mit Window implementiert. Woher kommt also die Vererbungsbeziehung?
Ist doch egal ob das Window heißt? Warum ist ein Button kein Fenster? Denn ein Fenster (mit der Titelleiste und Schliessen-Kreuz) in MS-Windows oder z.B. KDE ist auch nur ein weiteres Control _im_ Desktop. Also kann man sagen, alles ist ein Fenster. Wie es dargestellt wird, und man es als Knopf visualisiert, ist ein anderes Thema.
Hättest ihm lieber eine Lösung anbieten sollen...
-
.filmor schrieb:
Ein Button ist kein Window und er ist auch nicht mit Window implementiert.
Ein button IST EBEN SCHON ein Window, aber das würde jetz zusehr in die API abgleiten...
Dann solltest Du den Namen am Besten per Konstruktor an die Basisklasse übergeben und garkeinen Setter anbieten...
jup, aber gehn dann nicht solche sachen wie
Button* b = new Window("name");?
PS: Mann, die Leute hier sin echt schnell

-
Button b = new Window geht sowieso nicht, wenn dann Button *b = new Window, aber das geht auch nicht weil ein Window kein Button ist. Wenn überhaupt geht Window *b = new Button...
-
DeX3 schrieb:
.filmor schrieb:
Ein Button ist kein Window und er ist auch nicht mit Window implementiert.
Ein button IST EBEN SCHON ein Window, aber das würde jetz zusehr in die API abgleiten...
Dann hat die API eine krumme Logik...
(Ein Button ist kein Window!)DeX3 schrieb:
jup, aber gehn dann nicht solche sachen wie
Button b = new Window("name");?
Bitte schreib den Code sorgfältiger. Wenn du Button***** meintest, das geht genauso wenig wie der Code den du geschrieben hast. Ein Basisklassenzeiger ist nich implizit in einen Zeiger einer abgeleiteten Klasse umwandelbar, das geht nur andersherum. Dein Code (so wie er da steht) müsste glaub ich so aussehen:
Button b = *static_cast<Button*>(new Window("name"));Das ist aber völlig kaputt, gibt spätestens zur Laufzeit tolle Fehler (und ein Memory-Leak).
/edit zu spät
-
Pragmatisches Vorgehen:
Mache die Set-Funktion virtuel. Überschreibe sie in der abgeleiteten Klasse mit einer leeren Funktion und mache sie dort private.Ansonsten würde ich sagen ist es ziemlich sinnfrei eine Variable in den Objekten einer Klasse immer gleich belegt sein muss. Dies weisst auf ein Designfehler hin.
Was mir nicht so klar ist, wieso ein Button immer "Button" heißen soll. Das ein Button ein Button ist hat man ja schon durch die Klasse modelliert.
Ansonsten stelle ich mir einfach mal vor alle Buttons auf dem Bildschirm wären mit Button beschriftet.... sehr sinnnig...
-
LordJaxom schrieb:
Button b = new Window geht sowieso nicht, wenn dann Button *b = new Window, aber das geht auch nicht weil ein Window kein Button ist. Wenn überhaupt geht Window *b = new Button...
sry, da hab ich doch glatt nen * vergessen... ich werds editieren
Siehst du, das ist genau das was ich noch nicht ganz versteh.
Die abgeleitete Klasse kann doch noch zusätliche funktionen, instanzvariablen, usw. haben die die Basisklasse nicht hat.
Wie kann dann folgendes gehen:
Window *b = new Button();
-
Du kannst so nur auf die Funktionalität der Basisklasse zugreifen.
-
Mathias schrieb:
Pragmatisches Vorgehen:
Mache die Set-Funktion virtuel. Überschreibe sie in der abgeleiteten Klasse mit einer leeren Funktion und mache sie dort private.Ansonsten würde ich sagen ist es ziemlich sinnfrei eine Variable in den Objekten einer Klasse immer gleich belegt sein muss. Dies weisst auf ein Designfehler hin.
Was mir nicht so klar ist, wieso ein Button immer "Button" heißen soll. Das ein Button ein Button ist hat man ja schon durch die Klasse modelliert.
Ansonsten stelle ich mir einfach mal vor alle Buttons auf dem Bildschirm wären mit Button beschriftet.... sehr sinnnig...mit name ist ja auch nicht der titel des buttons gemeint sondern der name der fensterklasse, aber das ist ja schon wieder WinAPI...
thx für deine antwort ich wollts eig. genauso machen, wusste allerdings nicht das man die funktion dann im nachhinein private machen kann. Jedenfalls ist das genau wonach ich gesucht hab'
-
DeX3 schrieb:
Die abgeleitete Klasse kann doch noch zusätliche funktionen, instanzvariablen, usw. haben die die Basisklasse nicht hat.
Wie kann dann folgendes gehen:
Window *b = new Button();Wir filmor schon sagte, kannst Du mit b natürlich nur Funktionen ansprechen, die in Window enthalten sind (u.U. sind diese aber virtuell und in Button überschrieben, das nennt man dann Polymorphie).
Wenn Du mit Deinem Argument nochmal hierüber nachdenkst:
Button *b = new Window();Müsste eigentlich klar sein dass das nicht geht, weil ein Button ja viel mehr als ein Window hat, folglich "ein Teil von b" nicht definiert ist weil nur ein Window konstruiert ist. Gut dass der Sprachstandard das nicht zulässt

-
.filmor schrieb:
Du kannst so nur auf die Funktionalität der Basisklasse zugreifen.
ahaaaaaaa *große erleuchtung*
-
Artchi schrieb:
class Button : Window { public: basic_string<TCHAR> GetName() { return "Button"; } void SetName(basic_string<TCHAR> neu) { } };Button b1, b2;
b1.SetName("fred");
b2.Window::SetName("fred");
assert(b1.GetName() == "Button" && b2.Window::GetName() == "fred" && "Wie intuitiv!");
Wie sagt Scott Meyers doch so schön:
Never redefine an inherited nonvirtual function
Mache die Set-Funktion virtuel. Überschreibe sie in der abgeleiteten Klasse mit einer leeren Funktion und mache sie dort private.
Mit Noop-Überschreibung muss man sehr aufpassen, da sie sehr schnell das LSP verletzten (bzw: auch das "require no more, promise no less"-Prinzip). Wenn die Basisklassenversion sagt: "ändert den Namen", dann wäre eine noop-Überschreibung nicht korrekt.
Sollte der Basisklassen-Vertrag hingen sagen: "ändert den Namen oder auch nicht", dann würde ich mich fragen, warum die Methode nicht pure ist bzw. warum die Methode überhaupt Teil des Basis-Interfaces ist.
Eine weitere mögliche Überlegung: gehört das Name-Attribut überhaupt in die Window-Klasse? Oder ist es vielleicht optional?