Überladen virtueller Funktionen C++

Gast #1886054
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
Gast #1886064
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)
Gast #1886095
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?
#1886103
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren