using bei abgeleiteten klassen
-
hallo,
kann mir jemand sagen wann ich funktionen einer klasse mit using einbinden muss und wann sie automatisch zur verfügung stehen? ich blick da nämlich noch nicht ganz durch wann ich using brauche und wann nicht.
danke schon mal im voraus.
grüße
-
Der Name jeder public/protected Funktion der Basisklasse ist auch in abgeleiteten Klassen grundsaetzlich zugaenglich. Solltest du allerdings eine Funktion der Basisklasse in der abgeleiteten Klasse ueberschreiben, verdeckst du damit alle weiteren Funktionen gleichen Namens in der Basisklasse:
class C { public: virtual void Foo(); void Foo(int); void Foo(double); }; class D : public C { public: void Foo(int); //verdeckt C::Foo(int) und C::Foo(double) using C::Foo; //macht die beiden wieder sichtbar };Der Grund ist, dass der Compiler, sobald er einen Namen sieht, immer erst im umgebenden Namespace nachschaut, dann in dessen umgebenden Namespace und so weiter, bis er einen entsprechenden Namen findet. Ist ein (oder mehrere) Name gefunden, wird nicht weiter gesucht und ueberprueft, welcher der gefundenen Namen am Besten zum Aufruf passt, und danach, ob der Zugriff verfuegbar ist (public etc).
-
ist das auch so wenn die beiden funktionen zwar den gleichen namen aber unterschiedliche parameter haben.
warum sind denn die parameter dabei irrelevant, ich meine wenn die auch gleich sind kann ich es ja nachvollziehen das man die nicht sieht, wegen der lokalität. aber das bei deinem beispiel die foo(double) auch überdeckt find ich eigenartig. naja dann muss ich wohl überall ein using bei mir reinnehmen.
-
Der Compiler sucht als erstes nur nach dem Namen. Hat er den gefunden, schaut er, dass er den tatsaechlichen Funktionsparameter moeglichst gut mit den formalen Parametern der gefundenen Funktionen matchen kann, zur Not durch implizite Konvertierungen.
Laesst man in meinem Beispiel das using weg und ruft Foo fuer ein D auf, findet er D::Foo(int) und hoert sofort auf zu suchen. Dann versucht er, den uebergebenen Parameter (egal was fuer einer das ist, oder obs mehr als einer ist) zum int zu machen.
Ein aehnliches Problem ist folgendes:
class C { Foo(double); public: Foo(float); }; int main() { C c; c.Foo(23.56); //Error: Foo(double) is private c.Foo(23); //Error: ambigue overload of Foo() }Man koennte denken, dass ganz klar beidemale Foo(float) aufgerufen werden muss, da Foo(double) ja private ist, aber da der Compiler erst nach der Signatur guckt, findet er, dass Foo(double) ein perfekter Match fuer 23.56 ist und findet danach erst raus, dass das private ist und damit nicht zugaenglich. bei Foo(23) stellt er fest, dass die Konvertierung von int nach float und double gleich gut ist und kann sich nicht entscheiden - die Zugru=iffsrechte zieht er garnicht erst in Betracht.
-
pumuckl schrieb:
Man koennte denken, dass ganz klar beidemale Foo(float) aufgerufen werden muss, da Foo(double) ja private ist, aber da der Compiler erst nach der Signatur guckt, findet er, dass Foo(double) ein perfekter Match fuer 23.56 ist und findet danach erst raus, dass das private ist und damit nicht zugaenglich. bei Foo(23) stellt er fest, dass die Konvertierung von int nach float und double gleich gut ist und kann sich nicht entscheiden - die Zugru=iffsrechte zieht er garnicht erst in Betracht.
Ganz schön dumm, so ein C++-Compiler

-
Badestrand schrieb:
Ganz schön dumm, so ein C++-Compiler

Jein. Stell dir vor er machts anders und du wechselst irgendwann in einer Klasse die Zugriffsrechte einer Funktion. Das Programm haette sofort eine voellig andere Aussage weil eine andere Funktion aufgerufen wuerde - nur durch die Aenderung der Zugriffsrechte.
-
pumuckl schrieb:
Badestrand schrieb:
Ganz schön dumm, so ein C++-Compiler

Jein. Stell dir vor er machts anders und du wechselst irgendwann in einer Klasse die Zugriffsrechte einer Funktion. Das Programm haette sofort eine voellig andere Aussage weil eine andere Funktion aufgerufen wuerde - nur durch die Aenderung der Zugriffsrechte.
Das ist doch jetzt auch schon so, nur eben nicht in dem von Dir beschriebenen Spezialfall.
EDIT: Alles Quatsch.
-
gut dann mach ich das jetzt halt mit dem using. ist zwar mehr schreibarbeit, die konzeptmäßig nicht notwendig wäre, aber ist wohl nicht zu ändern.
-
pumuckl schrieb:
Der Name jeder public/protected Funktion der Basisklasse ist auch in abgeleiteten Klassen grundsaetzlich zugaenglich. Solltest du allerdings eine Funktion der Basisklasse in der abgeleiteten Klasse ueberschreiben, verdeckst du damit alle weiteren Funktionen gleichen Namens in der Basisklasse:
class C { public: virtual void Foo(); void Foo(int); void Foo(double); }; class D : public C { public: void Foo(int); //verdeckt C::Foo(int) und C::Foo(double) using C::Foo; //macht die beiden wieder sichtbar };fast:
die deklarationvoid Foo(int)verdeckt alle Foos aus C, und die using deklaration in diesem beispiel macht nurC::Foo(double)undC::Foo()wieder sichtbar. (C::Foo(int)wird immer noch vonD::Foo(int)verdeckt)damit der code zu deiner beschreibung passt:
class D : public C { public: void Foo(); //überschreibt C::Foo(), verdeckt C::Foo(int) und C::Foo(double) using C::Foo; //macht C::Foo(int) und C::Foo(double) wieder sichtbar. };
-
Ja sry, hatte das Beispiel von woanders kopiert, wo ich es schonmal gemacht hatte. Hab dann die Argumente geändert aber nicht die Kommentare
Typisches Beispiel von doppelter Information und einseitiger Änderung...