Compiler-Fehler bei einfacher Vererbung
-
Hi,
ich habe überhaupt gar keine Ahnung, warum folgender Code nicht compiliert. Habs mit VC 8 und g++ versucht, beide liefern denselben Fehler ("'B::Init' : function does not take 1 arguments").
Warum nur??? Ich dachte, das sei einfach nur Vererbung. Noch einfacher geht's ja fast nicht...
#include <string> class A { public: void Init(const std::string& s){}; virtual void Init(const std::string& s, int a){}; }; class B : public A { public: virtual void Init(const std::string& s, int a){}; }; int main() { B b; b.Init("Hallo!"); return 0; }Tausend Dank,
Felix
-
b.Init muss einen Integer als 2. paramerter bekommen
bei g++ geht das:#include <string> class A { public: void Init(const std::string& s){}; virtual void Init(const std::string& s, int a){}; }; class B : public A { public: virtual void Init(const std::string& s, int a){}; }; int main() { B b; b.Init("Hallo!", 1); return 0; }steht sogar im funktionskopf. hat nichts mit vererbung zu tuen
ich verordne dir als strafe 15 minuten tutorial lesn xD
-
Eine Deklaration verdeckt jede andere Deklaration gleichen Namens in einem äußeren Scope bzw. einer Basisklasse. Das Überschreiben der virtuellen Init-Funktion ist ebenfalls eine solche Deklaration und verdeckt die geerbte Init-Funktion aus A. Mehrere Varianten zur Abhilfe sind möglich:
1. durch qualifizierten Aufruf:int main() { B b; b.A::Init("Hallo!"); return 0; }2. durch Deklaration einer enstprechenden Überladung in B:
class B : public A { public: void Init(const std::string& s){ return A::Init(s); } virtual void Init(const std::string& s, int a){} };3. mittels using-Deklaration:
class B : public A { public: using A::Init; virtual void Init(const std::string& s, int a){} };
-
ABER: B erbt von A, ergo B erbt auch die Methoden von A. Und da A::Init(const std::string& s) definiert ist, sollte man auch b.Init("Hallo!") aufrufen können, oder???
-
camper schrieb:
Eine Deklaration verdeckt jede andere Deklaration gleichen Namens in einem äußeren Scope bzw. einer Basisklasse.
Ist das mit NAME ernst gemeint?!?! Oder Signatur?? Wobei -- da ich den Fehler bekomme, ist's wohl der Name...
Das finde ich aber sehr sehr verwirrend. Methoden sind normalerweise bei C++/Java/C#/... durch die Signatur (also Name UND Parameterliste) und nicht den Namen allein unterschieden.
Cheers,
Felix
-
Also das wäre mir auch neu, das der Name verdeckt wird. Ich müsste das für C++ auch noch mal speziell ausprobieren (meine tägliche Java-Arbeit sagt mir, das der Name nicht verdeckt wird!).
-
FelixManke schrieb:
Das finde ich aber sehr sehr verwirrend. Methoden sind normalerweise bei C++/Java/C#/... durch die Signatur (also Name UND Parameterliste) und nicht den Namen allein unterschieden.
Das ist auch richtig. Worauf du dich beziehst ist die Überladungsauflösung, wenn eine Funktion mehrere Überladungen hat. Bevor diese aber stattfinden kann, müssen aber erst einmal alle Überladungen, die in Frage kommen, gefunden werden. Dieser Vorgang (name lookup) berücksichtigt an sich nur den Namen.
-
Artchi schrieb:
Also das wäre mir auch neu, das der Name verdeckt wird. Ich müsste das für C++ auch noch mal speziell ausprobieren (meine tägliche Java-Arbeit sagt mir, das der Name nicht verdeckt wird!).
Weil die Funktion nur überschrieben wird? Das hat mich auch etwas unsicher gemacht, aber der Standard macht da keinen Unterschied. Eine große Rolle dürfte das kaum spielen, denn in der Regel werden virtuelle Funktionen wohl nicht überladen werden (oder man weicht auf des Template Pattern aus). D.h. Variante 4:
class A { public: void Init(const std::string& s){}; void Init(const std::string& s, int a) { return Init_impl(s,a); } private: virtual void Init_impl(const std::string& s, int a){}; }; class B : public A { private: virtual void Init_impl(const std::string& s, int a){}; };
-
camper hat Recht. Man kann es es sehen, wenn wann den Namen Init(const string&) in Init2(const string&) ändert. Dann ist der Compiler zufrieden. Nicht leicht verständlich, aber der C++-Standard sagt es so:
The declaration of a member in a derived class (clause 10) hides the declaration of a member of
a base class of the same name; see 10.2.