2009-05-20 4 views
40

Mögliche Duplizieren:
C++ overload resolutioneine Basis der überladenen Funktion in C++ Aufschalten

ich in ein Problem lief, wo nach meiner Klasse eine Funktion seiner Basisklasse overrode, die alle überladenen Versionen der Funktionen wurden dann ausgeblendet. Ist das Absicht oder mache ich etwas falsch?

Ex.

class foo 
{ 
    public: 
    foo(void); 
    ~foo(void); 
    virtual void a(int); 
    virtual void a(double); 
}; 

class bar : public foo 
{ 
    public: 
    bar(void); 
    ~bar(void); 
    void a(int); 
}; 

Das folgende würde dann einen Kompilierungsfehler geben, der besagt, dass es keine a (doppelte) Funktion in bar gibt.

main() 
{ 
    double i = 0.0; 
    bar b; 
    b.a(i); 
} 
+0

Es würde helfen, wenn Sie (wenn möglich) tatsächlichen Code gepostet. Der Code, den Sie gepostet haben, fehlen einige Details, wie Semikolons nach Klassendefinitionen und der Rückgabetyp für 'a' in' bar' ... –

+1

Ich kann den eigentlichen Code nicht posten. Ich fügte die Details in den Beitrag ein, dies war nicht wirklich eine Übung in Syntax. – Greg

+5

http://stackoverflow.com/questions/72010/c-overload-resolution –

Antwort

62

In der Klasse Bar, fügen

using foo::a; 

Dies ist eine gemeinsame 'Gotcha' in C++. Sobald eine Namensübereinstimmung im Klassenbereich gefunden wurde, wird der Vererbungsbaum für Überladungen nicht weiter untersucht. Indem Sie die 'using'-Deklaration angeben, bringen Sie alle Überladungen von' a 'von' foo 'in den Bereich von' bar '. Dann funktioniert das Überladen richtig.

Beachten Sie, dass bei vorhandenem Code mit der Klasse "foo" dessen Bedeutung durch die zusätzlichen Überladungen geändert werden kann. Oder die zusätzlichen Überladungen können Mehrdeutigkeit einführen und der Code wird nicht kompiliert.Darauf wird in James Hopkins Antwort hingewiesen.

+0

Perfekte Erklärung, vielen Dank! – Greg

+3

Es lohnt sich, den Hinweis von James Hopkin zu beachten, dass ein gültiger Code die Bedeutung ändert, wenn einer Basisklasse zusätzliche Funktionen hinzugefügt werden. –

+0

@Thomas: Bearbeitet, um diesen Punkt hinzuzufügen. Vielen Dank. –

18

So funktioniert die Sprache. Vor dem Schlüsselwort, wenn Sie eine überladene Funktion overrode, musste man sie zu überlasten alle:

class bar : public foo 
{ 
    public: 
    bar(void); 
    ~bar(void); 
    a(int); 
    a(double d) { foo::a(d); } // add this 
} 

Das ärgerte genug Leute, dass die Sprache Komitee der mit Funktion hinzugefügt, aber einige alte Gewohnheiten sterben schwer ; und die Habitués & Dolch; habe ein gutes Argument.

Wie James Hopkins darauf hinweist, indem er unter Verwendung hinzufügt, drückt der Programmierer die Absicht aus, dass die abgeleitete Klasse, ohne Warnung, zukünftige Überschreibungen von foo :: a() zu ihrer Liste akzeptabler Signaturen hinzufügt. Hier

ist ein Beispiel dessen, was er beschreibt: „Abgeleitet :: Double“

#include <iostream> 
class Base { 
public: 
    virtual void f(double){ std::cout << "Base::Double!" << std::endl; } 
    // virtual void f(int) { std::cout << "Base::Int!" << std::endl; } // (1) 
    virtual ~Base() {} 
}; 

class Derived : public Base { 
public: 
    // using Base::f; // (2) 
    void f(double) { std::cout << "Derived::Double!" << std::endl; } 
}; 

int main(int, char **) { 
    Derived d; 
    d.f(21); 
    return 0; 
} 

Der Ausgang wird weil der Compiler das Integer-Argument zu einem Double hochstufen wird. g ++ 4.0.1 -Wall wird nicht warnen, dass diese Aktion stattgefunden hat.

Uncomment (1), um eine zukünftige Änderung zu Base zu simulieren, indem die Methode Base :: f (int) hinzugefügt wird. Der Code kompiliert, wiederum ohne Warnung auch mit -Wall, und "Abgeleitet :: Double!" bleibt der Ausgang.

Entkommen Sie jetzt auskommentieren (2), um eine Entscheidung vom Abgeleiteten Programmierer zu simulieren, um alle Unterschriften :: f Signaturen einzuschließen. Der Code kompiliert (ohne Warnungen), aber die Ausgabe ist jetzt "Base :: Int!".

& Dolch; Ich kann mir kein englisches Wort für "diejenigen, die die Angewohnheit haben" vorstellen, und "süchtig" ist viel zu stark.

+0

Dies ist überhaupt nicht wahr, Sie können sehr gut nur eine Funktion überschreiben. –

+0

Meine einzige Verteidigung ist, dass ich vor 1996 eine Menge C++ geschrieben habe. Seufz. –

+0

Ah, die guten alten Zeiten :) –

11

Es ist beabsichtigt. Die Überladungsauflösung ist auf einen einzelnen Bereich beschränkt. Es verhindert einige unangenehme Fälle, in denen gültiger Code die Bedeutung ändert, wenn zusätzliche Funktionen zu einer Basisklasse oder zu einem Namensraumbereich hinzugefügt werden.

Verwandte Themen