Problem bei Ableitung und gleichnamiger Funktion mit anderen Parametern



  • Wenn ich folgendes Programm habe:

    class Basis
    {
    public:
    
    	virtual void Funktion ()
    	{
    	}
    };
    
    class Abgeleitet: public Basis
    {
    public:
    
    	virtual void Funktion (int i)
    	{
    	}
    };
    
    int main ()
    {
    	Abgeleitet a;
    
    	a.Funktion ();          //Fehler
    	//a.Basis::Funktion (); //So funktioniert es
    
    	return 0;
    }
    

    Warum funktioniert dann der Aufruf in Zeile 23 nicht? Dadurch, daß die Funktionen unterschiedliche Parameter haben, müßte die abgeleitete Klasse doch problemlos auf beide zugreifen können. Aber trotzdem muß ich hier die Basisklasse explizit mit angeben (Zeile 24). Warum ist das so?
    Und wie müßte ich das schreiben, wenn ich in beiden Klassen einen =-Operator hätte? Muß ich dann

    a.Basis::operator = (3);
    

    schreiben oder geht das auch kürzer/besser?



  • Mit der Funktion Funktion(int i) in Abgeleitet, versteckst du die Funktion Funktion() aus der Basis.

    Hier steht die Geschichte nochmal genauer: http://fara.cs.uni-potsdam.de/~kaufmann/?page=GenCppFaqs&faq=oho#Answ

    Edit:

    Generell läuft die Suche nach der passenden Funktion in drei Schritten ab:

    1. Bildung der Kandidatenmenge
    2. Auswahl der Funktionen mit passender Signatur aus der Kandidatenmenge
    3. Auswahl der am Besten passenden Funktion

    Für uns ist hier nur der erste Schritt wichtig.

    Ausgehend vom Scope in dem der Aufruf steht, kommen alle die Funktionen in die Kandidatenmenge, die den selben Namen haben wie die aufzurufende Funktion. Existiert in dem Scope keine solche Funktion, wird der darüberliegende Scope durchsucht. Umschließende Scopes werden also nur berücksichtigt, wenn in den eingeschlossenen Scopes keine gleichnamige Funktion existiert.


  • Mod

    Eine Name, der in einer abgeleiteten Klasse deklariert wird, verdeckt alle Entitäten gleichen Namens in den Basisklassen (es sei denn es handelt sich um das Überschreiben einer virtuellen Funktion - hier nicht der Fall). Diese können dann nur durch qualifizierten Aufruf gefunden werden. Die Verwendung einer using-Dekalartion kann das ändern - denn das entspricht einer Redeklaration aller Entitäten dieses Namens aus der jeweiligen Klasse. Also hier:

    class Abgeleitet: public Basis
    {
    public:
        using Basis::Funktion;
        virtual void Funktion (int i)
        {
        }
    };
    

    Ansonsten empfehle ich dafür die Lektüre eines Buches. Das Verständnis für die Problematik des Verdeckens von Namen und das Verhältnis zu Redeklaration und Überschreiben braucht ein bisschen Zeit und meine Erklärungen sind da etwas zu knapp.



  • Keine Sorge, ich weiß an sich, was es mit dem Verdecken von Funktionen bei Ableitungen und den Problemen damit auf sich hat.
    Ich hätte nur nicht gedacht, daß man das so realisiert hat, daß schon allein der Name der Funktion alle Funktionen aus der Basisklasse verdeckt. Meiner Meinung nach ist das schlecht umgesetzt, denn zwei Funktionen

    void Funktion ();
    void Funktion (int i);
    

    sind ohne Probleme durch ihre unterschiedlichen Parameter auseinanderzuhalten. Demnach, finde ich, sollte diese Verdeckung erst eintreten, wenn die Funktionen in den beiden Klassen den gleichen Namen und die gleichen Parameter haben.


  • Mod

    und was wäre bei

    void Funktion();
    void Funktion(int = 1);
    


  • Nun, dies ist ja an sich kein Problem des Verdeckens mehr, denn sowas kann auch auftreten, wenn ich innerhalb derselben Klasse zwei solche Funktionen schreibe. (Dann kommt beim Aufruf von Funktion () eben ein Fehler im Stil von: "Nicht eindeutiger Aufruf einer überladenen Funktion", so wie es ja jetzt auch der Fall ist.) Und das bedeutet: Dies ist kein guter Grund, Verdeckung schon allein am Namen festzumachen. Denn wie gesagt: So ein Problem kann ja ohnehin auftreten, auch wenn wir gar nicht mit Ableitungen arbeiten.


  • Mod

    nun ja, es ist nicht schwer, einige Gründe zu finden. Letzlich ist es ja bereits jetzt schon so, dass das Namelookup eher zu viel als zu wenig findet. Zudem bedeutet name lookup eben genau das: es wird nach Namen und nicht nach Signaturen gesucht - die Auswahl zwischen verschiedenen Überladungen kann hier noch gar nicht stattfinden. Zudem gäbe es ja sonst auch keine Möglichkeit, in verschachtelten Namensräumen Bezeichner aus den äußeren Namensräumen auch mal loszuwerden - was dem Sinn von Namensräumen doch etwas zuwiderläuft. Wenn ich in verschiedenen Namensräumen etwas mit dem gleichen Namen deklariere, handelt es sich normalerweise um völlig verschiedenen Dinge - deshalb stehen sie ja auch nicht zusammen. Dann soll aber auch der Anwender nicht raten müssen, was gefunden wird.


Anmelden zum Antworten