Design Frage
-
Ich habe eine kleine C++ Design Frage.
Nehmen wir an ich habe eine Klasse A mit einer virtuellen Methode, sowie eine Klasse B und C, die von A erben und die Methode überschreiben:class A { public: virtual void move(int X) = 0; }; class B : public A { public: void move(int X) { /* Code der X transfortmiert */ mit X arbeiten... } } class C : public A { public: void move(int X) { /* Code der X transfortmiert */ mit X arbeiten... } }Die Methoden in B und C kriegen einen Parameter, der erst bearbeitet (transformiert) wird und dann arbeiten beide mit X. Die Transformation ist in Klasse B und C identisch. Da der Transformationscode von X in allen Subklassen identisch ist, möchte ich ihn nun nach A schieben.
Irgendwie sollen die abgeleiteten Klassen von A also bereits das transformierte X bekommen.
Von der Logik her will ich also sowas (geht natürlich nicht, aber vom Sinn her):A* a = new B; a->move(X); // jetzt wird zuerst in A gesprungen, dass X transformiert und // dann die Methode move() von B aufgerufen, wobei das transformierte X übergeben wirdIst sowas machbar?
-
So in der Art?
class A { public: void move(int X) // Hier KEIN virtual mehr! { // X transformieren ... // Abgeleitete Klasse soll mit X arbeiten intern_move( X ); } private: virtual void intern_move( int X ) = 0; }; class B : public A { private: // PRIVATE, soll ja nicht von außen aufrufbar sein. void intern_move(int X) { /* X ist schon transfortmiert */ mit X arbeiten... } } class C : public A { private: void intern_move(int X) { /* X ist schon transfortmiert */ mit X arbeiten... } }PS: Damit klappt auch dein Codestückchen:
A* a = new B; a->move(X); // jetzt wird zuerst in A gesprungen, dass X transformiert und // dann die Methode intern_move() von B aufgerufen, wobei das transformierte X übergeben wird
-
Hm, das sieht wirklich schon mal gut aus.

2 kleine Fragen dazu:
1)Wieso kann intern_move private sein? Ich dachte alles was private ist, ist für Subklassen nicht zugreifbar/sichtbar? Ich könnte in B ja auch keine private Methode von A aufrufen, oder?- Wenn ich jetzt schreibe: A* a = new B; a->move(X); und er dann in move() aufruft: intern_move( X ); dann ist das ja im Grunde this->intern_move(X), oder? Welchen Typ hat dann this?
-
Hörncheneich schrieb:
1)Wieso kann intern_move private sein? Ich dachte alles was private ist, ist für Subklassen nicht zugreifbar/sichtbar? Ich könnte in B ja auch keine private Methode von A aufrufen, oder?
Kleiner Fehler meinerseits, hast natürlich Recht!
Hörncheneich schrieb:
- Wenn ich jetzt schreibe: A* a = new B; a->move(X); und er dann in move() aufruft: intern_move( X ); dann ist das ja im Grunde this->intern_move(X), oder? Welchen Typ hat dann this?
this hat dann den Typ A*, weil's ja in der Klasse A ist. virtual sorgt aber ja schon dafür, dass die richtige "intern_move"-Funktion aufgerufen wird, also die von B.
-
Badestrand schrieb:
Kleiner Fehler meinerseits, hast natürlich Recht!
Ich dachte dein Code geht nicht, weil ich eigentlich bis jetzt gedacht habe man kann in Subklassen keine private Member/Methoden verwenden. Zur Sicherheit habe ich deinen Code mal versucht zu kompilieren und es klappte! Jetzt bin ich etwas verwirrt, deshalb möchte ich hier nochmal nachfragen^^
Wie kann das sein das das geht? Der private Bereich soll doch die Implementierungsdetails verstecken. Eine virtual private Methode kann ich ja nur dann überschreiben, wenn ich sie kenne: sprich den private Bereich der Oberklasse. Ergibt für mich irgenwie keinen Sinn.
Badestrand schrieb:
this hat dann den Typ A*, weil's ja in der Klasse A ist. virtual sorgt aber ja schon dafür, dass die richtige "intern_move"-Funktion aufgerufen wird, also die von B.
Kann man sich das so vorstellen, dass im Speicher ein Block mit dem Teil von B und A liegt und er bei a->move(X); in den A teil springt? (obwohl ich ja ein B Objekt angelegt habe)
-
Hörncheneich schrieb:
Ich dachte dein Code geht nicht, weil ich eigentlich bis jetzt gedacht habe man kann in Subklassen keine private Member/Methoden verwenden. Zur Sicherheit habe ich deinen Code mal versucht zu kompilieren und es klappte! Jetzt bin ich etwas verwirrt, deshalb möchte ich hier nochmal nachfragen^^
Wie kann das sein das das geht? Der private Bereich soll doch die Implementierungsdetails verstecken. Eine virtual private Methode kann ich ja nur dann überschreiben, wenn ich sie kenne: sprich den private Bereich der Oberklasse. Ergibt für mich irgenwie keinen Sinn.
Hach, ich bin jetzt auch verwirrt. Aber eigentlich doch nicht, ist eigentlich einfach: Du kannst die Methode intern_move zwar überschreiben, auch wenn sie private ist, aber du kannst von B::intern_move nicht die Methode A::intern_move aufrufen, weil sie ja von A privat ist. Aber überschreiben geht. Und weil A quasi-denkt, dass es seine eigene intern_move-Methode aufruft, geht das in Ordnung, obwohl es (bei einem B-Objekt) ja dann Bs private intern_move-Methode aufruft.
Hörncheneich schrieb:
Kann man sich das so vorstellen, dass im Speicher ein Block mit dem Teil von B und A liegt und er bei a->move(X); in den A teil springt? (obwohl ich ja ein B Objekt angelegt habe)
Hm. Man kann bei Polymorphie (also Vererbung) auch von "statischem Typ" und "dynamischem Typ" reden. Bei
A* a=new B;ist von a der statische Typ A*, weil du a so deklariert hast. Der dynamische Typ ist aber B*, weil es eigentlich ein B-Objekt ist.
Wenn du jetzt auf diesem Objekt a Methoden aufrufst, entscheidet darüber welche Methode (Basisklasse oder abgeleitete Klasse) aufgerufen wird, ob die entsprechende Methode als "virtual" deklariert ist.
Ist die Methode virtual, wird nach dem dynamischen Typ gegangen, sonst nach dem statischen.a->move(X) ist aber eindeutig, erstens weil die Methode move nicht virtual ist und zweitens, weil es kein B::move gibt. Gäbe es auch in B ein move(int X), dann würde trotzdem A::move aufgerufen werden, da es in A nicht als virtual deklariert ist.
Wo in A::move die Methode intern_move bzw this->intern_move aufgerufen wird, wird nach dem dynamischen Typ gegangen, da die Methode intern_move virtual ist. intern_move ist in B überschrieben und der dynamische Typ ist in dem Fall B, also wird B::intern_move aufgerufen.
edit: Bin jetzt auch mal schlafen, Antwort also frühestens morgen früh

-
Badestrand schrieb:
edit: Bin jetzt auch mal schlafen, Antwort also frühestens morgen früh

Vielen Dank für deine Antworten.
Schlaf gut^^