Forum: PC-Programmierung Überladen virtueller Funktionen C++


von Tobias (Gast)


Lesenswert?

Hallo!

Kann mir jemand erklären, warum ich im Beispiel unten die überladene 
Funktion "doAmazingStuff" mit einem Parameter für ein Objekt der 
abgeleiteten Klasse nicht aufrufen kann?
1
#include <iostream>
2
3
class A
4
{
5
public:
6
  void doBoringStuff(double a) { doAmazingStuff(a, a/2); };
7
8
public:
9
  void doAmazingStuff(double a) { doAmazingStuff(a, a/2); };
10
  virtual void doAmazingStuff(double a, double b) = 0;
11
};
12
13
class B : public A
14
{
15
public:
16
  void doAmazingStuff(double a, double b) { std::cout << a << " " << b << std::endl; };
17
};
18
19
int main()
20
{
21
  A* a = new B;
22
  // OK
23
  a->doAmazingStuff(8);
24
25
  B b;
26
  // OK
27
  b.doBoringStuff(8);
28
  // Compiler error
29
  b.doAmazingStuff(8);
30
31
  return 0;
32
}

Vielen Dank!
Tobias

von Semikoln (Gast)


Lesenswert?

Welcher Compiler? Da sind doch Syntax-Fehler drin, oder?

von Tobias (Gast)


Lesenswert?

Standard GNU Compiler.

Keine Syntaxfehler.

Nur die Zeile "b.doAmazingStuff(8);" erzeugt folgenden Fehler:

test.cpp:29: error: no matching function for call to 
‘B::doAmazingStuff(int)’
test.cpp:16: note: candidates are: virtual void 
B::doAmazingStuff(double, double)

von Klaus W. (mfgkw)


Lesenswert?


von Tobias (Gast)


Lesenswert?

Vielen Dank! Das beantwortet meine Frage.

von Semikoln (Gast)


Lesenswert?

Tobias schrieb:
> Keine Syntaxfehler.
>
> Nur die Zeile "b.doAmazingStuff(8);" erzeugt folgenden Fehler:
>
> test.cpp:29: error: no matching function for call to
> ‘B::doAmazingStuff(int)’
> test.cpp:16: note: candidates are: virtual void
> B::doAmazingStuff(double, double)

Ja aber bitte schön!

Überladen wird der 'double, double' und aufgerufen mit 'double' (oder 
int). Das ist doch ein Fehler, oder?

von Karl H. (kbuchegg)


Lesenswert?

Und um die Frage nach dem 'warum' zu beantworten.

Das ist eine direkte Folge des Aufsuchalgorithmuses, den der Compiler 
benutzt um die richtige Funktion auszuwählen.

Der Compiler beginnt bei der abgeleiteten Klasse und arbeitet sich in 
Richtung Basisklasse vor. Er ist dabei auf der Suche nach der ersten 
Klasse, die eine oder mehrere Funktionen des angegebenen Namens enthält. 
Ist die Klasse erst einmal gefunden, dreht sich die Entscheidung nur 
noch darum, welche der Funktionen mit ihrer Parameterliste am besten zu 
den Argumenten passt. Falls gar keine passt, dann ist das ein Fehler, 
der Compiler beginnt nicht erneut sich in Richtung Basisklasse 
vorzuarbeiten und in einer Basisklasse eine besser passende Funktion zu 
finden.

In der Kurzfassung:
  zuerst wird ausgewählt, welche Klasse zuständig ist.
  dann wird aus dem Satz von verfügbaren Funktionen die am besten
  passende ausgewählt.


Da deine Klasse B eine Funktion
1
   void doAmazingStuff(double a, double b)
enthält, ist sie die Klasse unter deren Funktionen 'doAmazingStuff' 
ausgewählt wird.
Und da gibt es nun mal nur die eine, die 2 double nimmt.
Das ist aber unvereinbar mit
1
    b.doAmazingStuff(8);
und daher gibts den Fehler.

Die Klasse A, mit ihrer zusätzlichen Funktion doAmazingStuff, war 
überhaupt nie auch nur Kandidat, der in Betracht gezogen worden wäre.

Daher sagt man auch: Ein Funktion in einer abgeleiteten Klasse überdeckt 
(engl.: to hide) alle Funktionen gleichen Namens in den Basisklassen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.