ich habe da mal eine Frage zu virtuellen Funktionen.
Gegeben ist:
class A
{
public:
virtual void F() { cout << "func A" << endl; }
};
class B : public A
{
public:
void F() { cout << "func B" << endl; }
};
class C : public B
{
public:
void F() { cout << "func C" << endl; }
};
und diese werden wie folgt benutzt:
int main (int, char**)
{
A *a;
B b;
C c;
a = &b;
a->F(); <------------ 1
a = &c;
a->F(); <------------ 2
return 0;
}
1) Ok das ist Klar, A hat virtuelle Funktion. Diese wird von B ᅵberlagert.
2) Das ist mir jetzt nicht ganz Klar. C hat von B geerbt. B hat keine
virtuelle Funktion F(). Wieso ᅵberlagert C dann aber die Funktion F von A?
Mᅵᅵte da eigentlich nicht die "NICHT" virtuelle Funktion von B einen Riegel
vorschieben?
Gibt es fᅵr das verhalten eine Erklᅵrung?
Danke schon mal im Voraus.
Mario
[... Benutzung der Klassen...]
> 1) Ok das ist Klar, A hat virtuelle Funktion. Diese wird von B ᅵberlagert.
>
> 2) Das ist mir jetzt nicht ganz Klar. C hat von B geerbt. B hat keine
> virtuelle Funktion F(). Wieso ᅵberlagert C dann aber die Funktion F von A?
> Mᅵᅵte da eigentlich nicht die "NICHT" virtuelle Funktion von B einen Riegel
> vorschieben?
> Gibt es fᅵr das verhalten eine Erklᅵrung?
Ja. Wenn in einer Klasse eine Methode virtuell ist, ist sie es in allen
Klassen, die von dieser Klasse ableitet auch.
Deine Annahme, B hᅵtte keine virtuelle Methode ist also falsch.
Ich bevorzuge es, in den abgeleiteten Klassen auch ein 'virtual' vor der
Methodendeklaration zu schreiben, um nicht erst bei der Basisklasse
nachgucken zu mᅵssen. Dem Compiler ist's aber egal; B::F() ist virtuell.
Gruᅵ,
Helge
> class A
> {
> public:
> virtual void F() { cout << "func A" << endl; }
> };
>
> class B : public A
> {
> public:
> void F() { cout << "func B" << endl; }
> };
>
> class C : public B
> {
> public:
> void F() { cout << "func C" << endl; }
> };
> Gibt es fᅵr das verhalten eine Erklᅵrung?
Hallo,
leider schreibst du nicht, was fᅵr ein Verhalten es zeigt und was du
erwartet hast. Aber ich kann's mir denken.
Einmal virtual immer virtual. Du hast das optionale Schlᅵsselwort in
B nur weggelassen. Ich halte es fᅵr guten Stil, das immer
hinzuschreiben. Dann gibt es weniger Verwirrung.
class B : public A
{
public:
virtual void F() { cout << "func B" << endl; }
};
Was meinst Du? Was sollte Deiner Meinung nach c.F() ausgeben?
> Gibt es für das verhalten eine Erklärung?
Ja, sobald in der untersten Basisklasse einmal eine Funktion virtuell
ist, sind alle Ableitungen ebenfalls immer virtuell.
Gruß,
Nils
On 8 Nov., 23:01, Mario Schunda <weg_ma...@familie-schunda.de> wrote:
> Hallo,
>
> ich habe da mal eine Frage zu virtuellen Funktionen.
>
> Gegeben ist:
>
> class A
> {
> public:
> virtual void F() { cout << "func A" << endl; }
>
> };
>
> class B : public A
> {
> public:
> void F() { cout << "func B" << endl; }
>
> };
>
> class C : public B
> {
> public:
> void F() { cout << "func C" << endl; }
>
> };
>
> und diese werden wie folgt benutzt:
>
> int main (int, char**)
> {
> A *a;
> B b;
> C c;
>
> a = &b;
> a->F(); <------------ 1
>
> a = &c;
> a->F(); <------------ 2
>
> return 0;
>
> }
>
> 1) Ok das ist Klar, A hat virtuelle Funktion. Diese wird von B überlagert.
>
> 2) Das ist mir jetzt nicht ganz Klar. C hat von B geerbt. B hat keine
> virtuelle Funktion F(). Wieso überlagert C dann aber die Funktion F von A?
> Müßte da eigentlich nicht die "NICHT" virtuelle Funktion von B einen Riegel
> vorschieben?
> Gibt es für das verhalten eine Erklärung?
Ja, denn: einmal virtual, immer virtual. Wird in einer abgeleiteten
Klasse eine virtuelle methode einer Basisklasser ueberschrieben, dann
ist diese wieder virtual. D.h. F() in B ist wieder virtual und
entsprechend F() in C auch wieder.
Gruss,
Peer
Am besten, du ersetzt den Begriff "überlagert" durch "überschrieben",
sonst
versteht kein Mensch, was du meinst.
> 2) Das ist mir jetzt nicht ganz Klar. C hat von B geerbt. B hat keine
> virtuelle Funktion F().
Wieso sollte B keine virtuelle Funktion F() haben? Für ein Objekt mit
dem dynamischen Typ B ist B::F() der "final
overrider" ("Abschliessender
Überscheiber" hört sich ziemlich doof an, ich bleibe da lieber bei dem
englischen Terminus aus dem Standard). Für ein Objekt mit dem
dynamischen Typ C ist C::F() der "final overrider", usw.
> Wieso überlagert C dann aber die Funktion F von A?
> Müßte da eigentlich nicht die "NICHT" virtuelle Funktion von B einen Riegel
> vorschieben?
> Gibt es für das verhalten eine Erklärung?
Ja. Der Standard führt hierzu das Konzept des "final overrider" ein,
wie
oben angedeutet. Das kann man sich so vorstellen, dass innerhalb einer
Vererbungshierachie jeder Sub-Typ (abgeleitete Typ) eine in einer der
Basisklassen als solche ursprünglich definierte virtuelle Funktion
überschreiben kann, unabhängig davon, ob in einer Zwischenklasse
diese schon überschrieben wurde oder nicht. Überschreiben ist keine
"geht-nur-einmal"-Aktion, daher spricht der Standard hier von einem
"final overrider" einer virtuellen Funktion. Dies ist die virtuelle
Funktion
in einem Objekt mit dynamischen Typ T, die durch keine weitere
entsprechende Funktion in diesem Typ überschrieben wurde und sie
wird zur Laufzeit (wenn nicht anders qualifiziert) eines solchen
Objektes
ausgeführt.
Besten Gruss aus Bremen,
Daniel Krügler
> class A
> {
> public:
> virtual void F() { cout << "func A" << endl; }
> };
>
> class B : public A
> {
> public:
> void F() { cout << "func B" << endl; }
> };
>
> class C : public B
> {
> public:
> void F() { cout << "func C" << endl; }
> };
>
> 1) Ok das ist Klar, A hat virtuelle Funktion. Diese wird von B überlagert.
Genau. Und deshalb (weil B::F eine Reimplementation von A::F ist) wird ist
B::F auch virtual, selbst wenn Du es nicht hinschreibst.
> 2) Das ist mir jetzt nicht ganz Klar. C hat von B geerbt. B hat keine
> virtuelle Funktion F().
B hat (siehe oben) sehr wohl eine virtuelle Funktion.
Gruß,
Michael Karcher