2015-07-07 13 views
9

Ich dachte, ich verstehe Vererbung, und virtuelle Funktionen und Funktion Überladung, aber ich habe einen Fall, wo etwas über das Zusammenspiel zwischen diesen Funktionen mir entgeht.teilweise Vererbung von überladenen virtuellen Funktionen

Angenommen, ich habe eine einfache Basisklasse bekam eine überladene virtuelle Funktion, und eine zweite Klasse daraus abgeleiteten enthält:

class b { 
public: 
    virtual int f() { return 1; } 
    virtual int f(int) { return 2; } 
}; 


class d : public b { 
public: 
    virtual int f(int) { return 3; } 
}; 

Beachten Sie, dass die abgeleitete Klasse d überschreibt nur eine der überladenen virtuellen Funktionen.

kann ich ein Objekt der Klasse d und rufen f(int) darauf, kein Problem instanziiert:

d x; 
std::cout << x.f(0) << std::endl; 

Aber wenn ich versuche, die 0-Argument Funktion aufzurufen:

std::cout << x.f() << std::endl; 

es nicht! gcc sagt "keine übereinstimmende Funktion für den Aufruf von 'd :: f()'; Kandidaten sind: virtual int d :: f (int)". clang sagt "zu wenig Argumente um zu funktionieren call, erwartet 1, habe 0; meintest du 'b :: f'?" Auch wenn d von b stammt, die eine 0-Argument f()-Methode hat, ignoriert der Compiler das und versucht stattdessen d 1-Argument-Methode aufzurufen.

Ich kann dieses Problem beheben, indem die Definition der 0-Argument Funktion in der abgeleiteten Klasse zu wiederholen:

class d : public b { 
public: 
    virtual int f() { return 1; } 
    virtual int f(int) { return 3; } 
}; 

Oder, wie durch Klirren der Fehlermeldung vorgeschlagen, ich doof Begriffsklärung Syntax verwenden kann, den ich nie würde funktionieren würde erraten haben:

std::cout << x.b::f() << std::endl; 

Aber meine Frage ist, welche Regel habe ich brechen, und was diese Regel versucht zu erzwingen/schützen/verteidigen? Was ich hier zu tun versuchte, war genau die Art von Sache, für die ich das Erbe hielt.

+0

diese eine sehr gute Diskussion des Themas http://stackoverflow.com/questions/1628768/why-does-an-overridden-function-in-the-derived-class -Hide-Other-Überlastungen-der- – blade

Antwort

7

Dies ist bekannt als Name versteckt.

Wenn Sie eine Funktion mit demselben Namen in der abgeleiteten Klasse deklarieren, werden alle Funktionen mit demselben Namen in der Basis ausgeblendet.

Um uneingeschränkten Zugang zu ihnen zu erhalten, fügen Sie eine using Erklärung in der abgeleiteten Klasse:

class d : public b { 
public: 
    using b::f; 
    virtual int f(int) { return 3; } 
}; 
+1

Ist es in den Normen? –

+3

@OthmanBenchekroun [basic.scope.hiding]/1 'Ein Name kann durch eine explizite Deklaration desselben Namens in einer verschachtelten deklarativen Region oder abgeleiteten Klasse verborgen werden.' – TartanLlama

+0

@OthmanBenchekroun Auch in 13.2 Deklarationsabgleich, mit dem gleichen Beispiel (oder fast so) gegeben von Steve – marom

2

Eine Erklärung neben @ TartanLlama Antwort:

Wenn der Compiler den Aufruf zu lösen hat zu f, hat es drei wichtigsten Dinge in der Reihenfolge:

  1. Namenssuche. Bevor Sie etwas anderes tun, sucht der Compiler nach einem Bereich, der mindestens eine Entität mit dem Namen f enthält, und erstellt eine Liste mit Kandidaten. In diesem Fall sucht die Namenssuche zuerst im Bereich d, um festzustellen, ob mindestens ein Element namens f vorhanden ist. Wenn dies nicht der Fall wäre, würden Basisklassen und umschließende Namespaces der Reihe nach nacheinander betrachtet werden, bis ein Bereich mit mindestens einem Kandidaten gefunden wurde.In diesem Fall hat jedoch der allererste Bereich, in den der Compiler hineinschaut, eine Entität mit dem Namen f, und dann wird die Namenssuche beendet.

  2. Überladungsauflösung. Als nächstes führt der Compiler eine Überladungsauflösung durch, um die eindeutig beste Übereinstimmung aus der Kandidatenliste auszuwählen. In diesem Fall stimmt die Anzahl der Argumente nicht überein und schlägt fehl.

  3. Überprüfung der Zugänglichkeit. Schließlich führt der Compiler eine Überprüfung der Zugänglichkeit durch, um festzustellen, ob die ausgewählte Funktion aufgerufen werden kann.

Referenz für Name lookup

Verwandte Themen