Hypercell ein ] Hypercell aus ] Zeige Navigation ] Verstecke Navigation ]
c++.de  
   

Die mobilen Seiten von c++.de:
http://m.c-plusplus.de
Infos hier [BETA]

  
c++.de :: FAQ - C++ (auch C++0x, C++11) ::  Basisklassenmethode in abgeleiteter Klasse überladen - Wie?     Zeige alle Beiträge auf einer Seite Auf Beitrag antworten
Autor Nachricht
kartoffelsack
Mitglied

Benutzerprofil
Anmeldungsdatum: 26.07.2001
Beiträge: 1401
Beitrag kartoffelsack Mitglied 11:57:00 11.12.2001   Titel:   Basisklassenmethode in abgeleiteter Klasse überladen - Wie?            Zitieren

Ich bin ein bisschen überascht, das folgendes nicht geht:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class CBase
{
public:
  void a() {;};
};
 
class CChild  :public CBase
{
public:
  void a(int i) {;};
};
 
int main()
{
  CChild Child;
  Child.a();
}


Die Überladung a(int i) von CChild scheint das a() zu überdecken. Aber warum a() und a(int i) sind doch zwei völlig verschiedene Schuhe (und im grunde ist es für den Compiler doch genauso unterschiedlich wie a() und b(int i) :confused:


Zuletzt bearbeitet von Gerard am 00:08:54 24.01.2004, insgesamt 1-mal bearbeitet
Werbeunterbrechung
HumeSikkins
Mitglied

Benutzerprofil
Anmeldungsdatum: 30.08.2000
Beiträge: 11139
Beitrag HumeSikkins Mitglied 12:23:00 11.12.2001   Titel:              Zitieren

Hallo,
Überladung funktioniert immer nur auf der Ebene eines Sichtbarkeitsbereichs. Nie über die Grenzen einen solchen hinaus. Da sowohl CBase, als auch CChild eigene Scopes besitzen, findet hier keine Überladung sondern eine Überdeckung statt.
Die Lösung:
Befördere a in den Scope von CChild. Dies geschieht über eine using-Deklaration.
Hier findest du mehr: http://fara.cs.uni-potsdam.de/~kaufmann/index.php?page=GenCppFaqs&faq=Overload#Answ

[ Dieser Beitrag wurde am 08.01.2002 um 14:50 Uhr von HumeSikkins editiert. ]

_________________
Remember Sturgeon's Law:
"Ninety percent of everything is crap."
and now go visit my Homepage ;-)
kartoffelsack
Mitglied

Benutzerprofil
Anmeldungsdatum: 26.07.2001
Beiträge: 1401
Beitrag kartoffelsack Mitglied 12:38:00 11.12.2001   Titel:              Zitieren

C++:
 Wird über eine solche Instanz eine Methode aufgerufen, schaut der Compiler
als erstes in den Scope der Klasse. Da er hier eine Methode Func findet, endet die Namensauflösung. Weitere Scopes werden
nicht mehr berücksichtig. Tatsächlich überdeckt Func aus Derived also Func aus Base.


Naja, aber in meinem Fall findet sich ja keine passende Methode im Scope von CChild. Das müsste er sich doch automatisch denken, dass man da ja noch bei CBase nachgucken könnte [img]images/smiles/icon_rolleyes.gif[/img] - stattdessen krieg ich nen Fehler

[ Dieser Beitrag wurde am 11.12.2001 um 11:43 Uhr von kartoffelsack editiert. ]
tunichtgut
Mitglied

Benutzerprofil
Anmeldungsdatum: 03.05.2001
Beiträge: 223
Beitrag tunichtgut Mitglied 12:52:00 11.12.2001   Titel:              Zitieren

Das verhalten ist schon ganz richtig so. Überschreibe ich die funktion einer klasse, so hat das meißt seinen grund. Diese funktion wird meißt anders arbeiten als die der basisklasse. In der Basisklasse gibt es z.b. ein f(int), in der abgeleiteten klasse ein f(unsigned). Jetzt kommt folgendes:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class CBase
{
public:
  void a(int) {;};
};
 
class CChild   :public CBase
{
public:
  void a(unsigned) {;};
};
 
int main()
{
  CChild Child;
 
  int a = 5;
  unsigned b = 6;
 
  Child.a(a+b);  // Welche funktion ist gemeint?
}

Welche funktion soll ausgeführt werden? Auf jeden fall hat das f der basis die bessere übereinstimmung - Funktionen überläd man jedoch gerade wegen veränderter funktionalität. Im oben angegebenen beispiel ist der typ von a+b eindeutig (?), ist aber schwer zu erkennen. Der programmierer wundert sich dann nachher, das die falsche funktion aufgerufen wird. An einen cast um den funktionsaufruf eindeutig zu machen denkt man in dem augenblick wohl nicht. Aus sicherheitsgründen hat man daher gleich alle funktionen der basis (wenn sie überschrieben werden) ausgeknipst. Aber es gibt eine möglichkeit funktionen der basisklasse trotzdem weiterhin zu zulassen.
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class CBase
{
public:
  void a() {;};
};
 
class CChild   :public CBase
{
public:
  void a(int i) {;};
  using CBase::a;  // <- so geht es auch
};
 
int main()
{
  CChild Child;
  Child.a();
}

Eine explizite using-anweisung hilt in diesem beispiel.

[ Dieser Beitrag wurde am 11.12.2001 um 11:55 Uhr von tunichtgut editiert. ]

_________________
Sagt was ihr wollt...
Meine Antwort ist 42!


Zuletzt bearbeitet von Gerard am 00:09:21 24.01.2004, insgesamt 1-mal bearbeitet
HumeSikkins
Mitglied

Benutzerprofil
Anmeldungsdatum: 30.08.2000
Beiträge: 11139
Beitrag HumeSikkins Mitglied 13:56:00 11.12.2001   Titel:              Zitieren

@kartoffelsack
Namensauflösung basiert zunächst erstmal nur auf dem Methodenname (hier also nur a). Erst ein Schritt später wird die am besten passende Methode ausgewählt (basierend auf der kompletten Signatur).
Allgemein geht es immer so:

1. Suche alle sichtbaren Namen (nur Name der Funktion)
Namen eines Scopes verdecken die Namen eines darüberliegenden Scopes.
2. Wähle alle aufrufbaren Funktionen (anhand der Signatur).
3. Wähle die beste Übereinstimmung.

Situation 1 (dein Beispiel):
1. Suche alle sichtbaren Namen:
Die Methode CChild::a ist die einzig sichtbare. Weitere Scopes werden nicht mehr durchsucht.
2. Wähle alle aufrufbaren Funktionen: Schade, keine da.
3. Keine
--> Compilerfehler.

Situation 2 (wie oben, nur CChild überschreibt a nicht):
1. Die Suche im Scope von CChild ergibt nichts. Also wird der nächst höhere Scope durchsucht. Ergebnis: CBase::a
2. CBase::a hat eine passende Signatur
3. CBase::a ist die einzige passende Funktion -> wird also aufgerufen.

Situation 3 (mit using-Deklaration):
1. Die Suche in CChild ergibt: CChild::a und CBase::a
2. Nur CBase::a hat eine passende Signatur
3. CBase::a ist die einzige passsende Funktion -> wird aufgerufen.

Situation 4 (mit einer weiteren Methode Child::a(double) und using-Deklaration)
1. Die Suche in CChild ergibt: 2 x Child::a, CBase::a
2. CBase::a und CChiild::a(double) sind aufrufbar.
3. CBase::a ist der "best match", da CChild::a(double) noch eine Promotion int->double erfordern würde. CBase::a hingegen erfordert keine Konvertierung.

_________________
Remember Sturgeon's Law:
"Ninety percent of everything is crap."
and now go visit my Homepage ;-)
c++.de :: FAQ - C++ (auch C++0x, C++11) ::  Basisklassenmethode in abgeleiteter Klasse überladen - Wie?   Auf Beitrag antworten

Zeige alle Beiträge auf einer Seite




Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Sie können keine Beiträge in dieses Forum schreiben.
Sie können auf Beiträge in diesem Forum nicht antworten.
Sie können Ihre Beiträge in diesem Forum nicht bearbeiten.
Sie können Ihre Beiträge in diesem Forum nicht löschen.
Sie können an Umfragen in diesem Forum nicht mitmachen.

Powered by phpBB © 2001, 2002 phpBB Group :: FI Theme

c++.de ist Teilnehmer des Partnerprogramms von Amazon Europe S.à.r.l. und Partner des Werbeprogramms, das zur Bereitstellung eines Mediums für Websites konzipiert wurde, mittels dessen durch die Platzierung von Werbeanzeigen und Links zu amazon.de Werbekostenerstattung verdient werden kann.

Die Vervielfältigung der auf den Seiten www.c-plusplus.de, www.c-plusplus.info und www.c-plusplus.net enthaltenen Informationen ohne eine schriftliche Genehmigung des Seitenbetreibers ist untersagt (vgl. §4 Urheberrechtsgesetz). Die Nutzung und Änderung der vorgestellten Strukturen und Verfahren in privaten und kommerziellen Softwareanwendungen ist ausdrücklich erlaubt, soweit keine Rechte Dritter verletzt werden. Der Seitenbetreiber übernimmt keine Gewähr für die Funktion einzelner Beiträge oder Programmfragmente, insbesondere übernimmt er keine Haftung für eventuelle aus dem Gebrauch entstehenden Folgeschäden.