 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Kai Henning Guest
|
Posted: Wed Jun 02, 2004 7:32 am Post subject: Virtuelle Ableitungen und Funktionszeiger |
|
|
Hallo,
weshalb keine die Adresse einer Methode einer
virtuell abgeleiteten Klasse nicht an ein Objekt
zugewiesen werden, welches die Adresse einer
Methode der Basisklasse speichert?
class AA
{
public:
void f();
};
class BB : virtual public AA
{
public:
void f();
};
typedef void (AA::*A_FUNC)();
A_FUNC af= &BB::f; <-- Fehlermeldung des Compilers
Wird nicht-virtuell abgeleitet ist die Zuweisung ohne Probleme
möglich. Getestet habe ich mit VC 6/7 und BCC 5.5 .
Kai
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Rolf Magnus Guest
|
Posted: Wed Jun 02, 2004 9:11 am Post subject: Re: Virtuelle Ableitungen und Funktionszeiger |
|
|
Kai Henning wrote:
| Quote: | Hallo,
weshalb keine die Adresse einer Methode einer
virtuell abgeleiteten Klasse nicht an ein Objekt
zugewiesen werden, welches die Adresse einer
Methode der Basisklasse speichert?
|
Äh, was?
| Quote: | class AA
{
public:
void f();
};
class BB : virtual public AA
{
public:
void f();
};
typedef void (AA::*A_FUNC)();
A_FUNC af= &BB::f; <-- Fehlermeldung des Compilers
|
Wie lautete diese Fehlermeldung denn?
Die Memberfunktion ist nicht virtuell, also nicht polymorph. Es kann
daher nie richtig sein, die Funktion f aus BB für ein AA aufzurufen.
Und wenn sie polymorph wäre, könnte man auch gleich &AA::f angeben. Es
gibt also keinen Grund, warum &BB::f an af zuweisbar sein sollte.
| Quote: | Wird nicht-virtuell abgeleitet ist die Zuweisung ohne Probleme
möglich. Getestet habe ich mit VC 6/7 und BCC 5.5 .
|
Das wäre seltsam. Mein g++ meldet in beiden Fällen den selben Fehler:
error: cannot convert `void (BB::*)()' to `void (AA::*)()' in
initialization
Comeau online meldet (ebenfalls in beiden Fällen):
error: a value of type "void (BB::*)()" cannot be used to initialize an
entity of type "A_FUNC"
A_FUNC af= &BB::f;
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Kai Henning Guest
|
Posted: Wed Jun 02, 2004 1:19 pm Post subject: Re: Virtuelle Ableitungen und Funktionszeiger |
|
|
Sorry, sollte natürlich heißen
"weshalb kann die Adresse einer ...."
~~~~
Die Zuweisung der Adresse einer Methode einer abgeleiteten Klasse an
ein Objekt, welches die Adresse einer Methode der Basisklasse
speichert ist z. B. im Zusammenhang mit der Entwicklung von
wxWidgets-, MFC- oder OWL-Programmen von Bedeutung. Die Einträge in
einer Antworttabelle zur Behandlung von Ereignissen sind vom Typ
"Funktion der Basisklasse", zugewiesen werden jedoch die Adressen von
Methoden einer abgeleiteten Klasse.
Kai
Rolf Magnus <ramagnus (AT) t-online (DOT) de> wrote
| Quote: | Kai Henning wrote:
Hallo,
weshalb keine die Adresse einer Methode einer
virtuell abgeleiteten Klasse nicht an ein Objekt
zugewiesen werden, welches die Adresse einer
Methode der Basisklasse speichert?
Äh, was?
class AA
{
public:
void f();
};
class BB : virtual public AA
{
public:
void f();
};
typedef void (AA::*A_FUNC)();
A_FUNC af= &BB::f; <-- Fehlermeldung des Compilers
Wie lautete diese Fehlermeldung denn?
Die Memberfunktion ist nicht virtuell, also nicht polymorph. Es kann
daher nie richtig sein, die Funktion f aus BB für ein AA aufzurufen.
Und wenn sie polymorph wäre, könnte man auch gleich &AA::f angeben. Es
gibt also keinen Grund, warum &BB::f an af zuweisbar sein sollte.
Wird nicht-virtuell abgeleitet ist die Zuweisung ohne Probleme
möglich. Getestet habe ich mit VC 6/7 und BCC 5.5 .
Das wäre seltsam. Mein g++ meldet in beiden Fällen den selben Fehler:
error: cannot convert `void (BB::*)()' to `void (AA::*)()' in
initialization
Comeau online meldet (ebenfalls in beiden Fällen):
error: a value of type "void (BB::*)()" cannot be used to initialize an
entity of type "A_FUNC"
A_FUNC af= &BB::f;
|
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Rolf Magnus Guest
|
Posted: Wed Jun 02, 2004 5:08 pm Post subject: Re: Virtuelle Ableitungen und Funktionszeiger |
|
|
Kai Henning wrote:
| Quote: | Sorry, sollte natürlich heißen
"weshalb kann die Adresse einer ...."
~~~~
Die Zuweisung der Adresse einer Methode einer abgeleiteten Klasse an
ein Objekt, welches die Adresse einer Methode der Basisklasse
speichert ist z. B. im Zusammenhang mit der Entwicklung von
wxWidgets-, MFC- oder OWL-Programmen von Bedeutung. Die Einträge in
einer Antworttabelle zur Behandlung von Ereignissen sind vom Typ
"Funktion der Basisklasse", zugewiesen werden jedoch die Adressen von
Methoden einer abgeleiteten Klasse.
|
Wieso? Wenn die Funktionen in der Basisklasse virtuell ist, braucht man
das nicht. Man gibt einfach einen Zeiger auf die Funktion in der
Basisklasse an und die Polymorphie besorgt den Rest.
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Kai Henning Guest
|
Posted: Thu Jun 03, 2004 6:19 am Post subject: Re: Virtuelle Ableitungen und Funktionszeiger |
|
|
Rolf Magnus <ramagnus (AT) t-online (DOT) de> wrote
| Quote: | Kai Henning wrote:
Sorry, sollte natürlich heißen
"weshalb kann die Adresse einer ...."
~~~~
Die Zuweisung der Adresse einer Methode einer abgeleiteten Klasse an
ein Objekt, welches die Adresse einer Methode der Basisklasse
speichert ist z. B. im Zusammenhang mit der Entwicklung von
wxWidgets-, MFC- oder OWL-Programmen von Bedeutung. Die Einträge in
einer Antworttabelle zur Behandlung von Ereignissen sind vom Typ
"Funktion der Basisklasse", zugewiesen werden jedoch die Adressen von
Methoden einer abgeleiteten Klasse.
Wieso? Wenn die Funktionen in der Basisklasse virtuell ist, braucht man
das nicht. Man gibt einfach einen Zeiger auf die Funktion in der
Basisklasse an und die Polymorphie besorgt den Rest.
|
Das Problem beim Einsatz von Frameworks (wie z. B. wxWidgets) ist
aber, dass die Basisklassen bereits vorgegeben sind und keine
virtuelle Methoden, die dem geforderten Typ entsprechen, besitzen.
Andererseits ist meine Frage, warum die Konvertierung nicht
durchführbar ist, nicht beantwortet, auch wenn ich das Problem durch
den Einsatz virtueller Methoden beseitigen würde.
Kai
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Kai Henning Guest
|
Posted: Thu Jun 03, 2004 8:34 am Post subject: Re: Virtuelle Ableitungen und Funktionszeiger |
|
|
Rolf Magnus <ramagnus (AT) t-online (DOT) de> wrote
| Quote: | Kai Henning wrote:
Hallo,
weshalb keine die Adresse einer Methode einer
virtuell abgeleiteten Klasse nicht an ein Objekt
zugewiesen werden, welches die Adresse einer
Methode der Basisklasse speichert?
Äh, was?
class AA
{
public:
void f();
};
class BB : virtual public AA
{
public:
void f();
};
typedef void (AA::*A_FUNC)();
A_FUNC af= &BB::f; <-- Fehlermeldung des Compilers
Wie lautete diese Fehlermeldung denn?
Die Memberfunktion ist nicht virtuell, also nicht polymorph. Es kann
daher nie richtig sein, die Funktion f aus BB für ein AA aufzurufen.
Und wenn sie polymorph wäre, könnte man auch gleich &AA::f angeben. Es
gibt also keinen Grund, warum &BB::f an af zuweisbar sein sollte.
Wird nicht-virtuell abgeleitet ist die Zuweisung ohne Probleme
möglich. Getestet habe ich mit VC 6/7 und BCC 5.5 .
Das wäre seltsam. Mein g++ meldet in beiden Fällen den selben Fehler:
error: cannot convert `void (BB::*)()' to `void (AA::*)()' in
initialization
Comeau online meldet (ebenfalls in beiden Fällen):
error: a value of type "void (BB::*)()" cannot be used to initialize an
entity of type "A_FUNC"
A_FUNC af= &BB::f;
|
Die Fehlermeldung des Compilers bei nicht virtueller Ableitung ist
wohl korrekt, da C++ keine Kontravarianz unterstützt. In diesem Fall
hilft jedoch ein reinterpret_cast<>
A_FUNC af= reinterpret_cast< A_FUNC >(&BB::f);
Es ist meine Aufgabe sicherzustellen, dass af nur im Zusammenhang mit
Objekten vom Typ BB eingesetzt wird. (BCC 5.5 und VC6 compilieren auch
ohne reinterpret_cast<> fehlerfrei.)
Bleibt also nur noch zu klären, warum es bei virtueller Ableitung und
Einsatz von reinterpret_cast<> nicht möglich ist, die Zuweisung
vorzunehmen. Dass die Zuweisung einen Fehler darstellt, damit habe ich
mich bereits abgefunden. Mich würde nur interessieren warum?
Kai Henning
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Falk Tannhäuser Guest
|
Posted: Thu Jun 03, 2004 5:02 pm Post subject: Re: Virtuelle Ableitungen und Funktionszeiger |
|
|
Kai Henning wrote:
| Quote: |
Hallo,
weshalb kann die Adresse einer Methode einer
virtuell abgeleiteten Klasse nicht an ein Objekt
zugewiesen werden, welches die Adresse einer
Methode der Basisklasse speichert?
class AA
{
public:
void f();
};
class BB : virtual public AA
{
public:
void f();
};
typedef void (AA::*A_FUNC)();
A_FUNC af = &BB::f; <-- Fehlermeldung des Compilers
Wird nicht-virtuell abgeleitet ist die Zuweisung ohne Probleme
möglich. Getestet habe ich mit VC 6/7 und BCC 5.5 .
|
Sicher soll danach irgendwann so ein Aufruf erfolgen:
BB beh;
(beh.*af)();
(Ansonsten wäre die ganze Geschichte ja witzlos...)
Wäre die fragliche Konversion erlaubt, ginge aber auch
AA aah;
(aah.*af)();
wodurch eine BB-Methode für ein AA-Objekt, welches kein BB-Objekt ist,
aufgerufen würde.
Mit reinterpret_cast lässt sich zwar das Programm übersetzen, doch kann
man mit dem so erhaltenen Funktionszeiger nichts weiter anfangen, außer
ihn in den Originaltyp zurückzucasten; ein Versuch, die Funktion aufzurufen,
ergibt "Nicht Definiertes Verhalten" (siehe 5.2.10/6 und 5.2.10/9).
Was hingegen unter bestimmten Voraussetzungen erlaubt ist, ist die umgekehrte
Konversion:
typedef void (BB::*B_FUNC)();
B_FUNC bf = &AA::f;
da AA::f für ein BB-Objekt aufgerufen werden darf.
Die Implementierung ist allerdings nicht ganz trivial, da
- virtuelle und nicht virtuelle Funktionen verschieden behandelt werden müssen
(wenn f in AA virtuell ist, dann muss '(beh.*bf)()' BB::f aufrufen und nicht
AA::f)
- im Falle einer nicht virtuellen Funktion f der Zeiger bf nicht nur die Adresse
von f speichern muss, sondern auch die Möglichkeit bieten muss, beim Aufruf
'(beh.*bf)()' erstmal die Adresse des AA-Unterobjekts innerhalb des BB-Objekts
beh zu ermitteln, um mit dieser dann den this-Zeiger von AA::f zu initialisieren.
Hierzu reicht es, den Offset zwischen diesen beiden Adressen zu speichern, da
dieser bei nicht virtueller Vererbung schon zur Übersetzungszeit feststeht.
(Man beachte, dass diese beiden Adressen nicht notwendigerweise gleich sind,
so z.B. im Falle von Mehrfachvererbung, virtueller Vererbung, oder mit manchen
Compilern auch, wenn BB polymorph ist und AA nicht - da der V-Table-Zeiger oft
zu Beginn des Objekts im Speicher abgelegt wird).
Darum nehmen übrigens Methodenfunktionszeiger auch meist mehr Platz ein als
normale Funktionszeiger (bei g++ für i686 z.B. 8 Bytes statt 4).
Bei virtueller Vererbung gäbe es allerdings noch mehr Problemchen:
class CC : virtual public AA
{
public:
void f();
};
class DD : public BB, public CC
{
};
void foo(BB& bref)
{
(bref.*bf)();
}
int main()
{
BB beh;
DD deh;
foo(beh);
foo(deh);
return 0;
}
Wie soll hier der Compiler die Adresse des AA-Unterobjekts aus bref in foo ermitteln?
Der Offset zwischen der Adresse des AA-Unterobjekts im BB-Objekt 'beh' ist ja nicht
derselbe, wie der Offset zwischen der Adresse des AA-Unter-Unterobjekts des BB-Unterobjekts
des DD-Objekts 'deh'. Daher kann er in foo nicht ermittelt werden :-(
Aus diesem Grunde unterstützt der Standard die genannte Konversion im Falle von virtueller
Vererbung nicht, siehe hierzu 4.11/2.
MfG
Falk
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Falk Tannhäuser Guest
|
Posted: Thu Jun 03, 2004 5:16 pm Post subject: Re: Virtuelle Ableitungen und Funktionszeiger |
|
|
Kai Henning wrote:
| Quote: |
Hallo,
weshalb kann die Adresse einer Methode einer
virtuell abgeleiteten Klasse nicht an ein Objekt
zugewiesen werden, welches die Adresse einer
Methode der Basisklasse speichert?
class AA
{
public:
void f();
};
class BB : virtual public AA
{
public:
void f();
};
typedef void (AA::*A_FUNC)();
A_FUNC af = &BB::f; <-- Fehlermeldung des Compilers
Wird nicht-virtuell abgeleitet ist die Zuweisung ohne Probleme
möglich. Getestet habe ich mit VC 6/7 und BCC 5.5 .
|
Sicher soll danach irgendwann so ein Aufruf erfolgen:
BB beh;
(beh.*af)();
(Ansonsten wäre die ganze Geschichte ja witzlos...)
Wäre die fragliche Konversion erlaubt, ginge aber auch
AA aah;
(aah.*af)();
wodurch eine BB-Methode für ein AA-Objekt, welches kein BB-Objekt ist,
aufgerufen würde.
Mit reinterpret_cast lässt sich zwar das Programm übersetzen, doch kann
man mit dem so erhaltenen Funktionszeiger nichts weiter anfangen, außer
ihn in den Originaltyp zurückzucasten; ein Versuch, die Funktion aufzurufen,
ergibt "Nicht Definiertes Verhalten" (siehe 5.2.10/6 und 5.2.10/9).
Was hingegen unter bestimmten Voraussetzungen erlaubt ist, ist die umgekehrte
Konversion:
typedef void (BB::*B_FUNC)();
B_FUNC bf = &AA::f;
da AA::f für ein BB-Objekt aufgerufen werden darf.
Die Implementierung ist allerdings nicht ganz trivial, da
- virtuelle und nicht virtuelle Funktionen verschieden behandelt werden müssen
(wenn f in AA virtuell ist, dann muss '(beh.*bf)()' BB::f aufrufen und nicht
AA::f)
- im Falle einer nicht virtuellen Funktion f der Zeiger bf nicht nur die Adresse
von f speichern muss, sondern auch die Möglichkeit bieten muss, beim Aufruf
'(beh.*bf)()' erstmal die Adresse des AA-Unterobjekts innerhalb des BB-Objekts
beh zu ermitteln, um mit dieser dann den this-Zeiger von AA::f zu initialisieren.
Hierzu reicht es, den Offset zwischen diesen beiden Adressen zu speichern, da
dieser bei nicht virtueller Vererbung schon zur Übersetzungszeit feststeht.
(Man beachte, dass diese beiden Adressen nicht notwendigerweise gleich sind,
so z.B. im Falle von Mehrfachvererbung, virtueller Vererbung, oder mit manchen
Compilern auch, wenn BB polymorph ist und AA nicht - da der V-Table-Zeiger oft
zu Beginn des Objekts im Speicher abgelegt wird).
Darum nehmen übrigens Methodenfunktionszeiger auch meist mehr Platz ein als
normale Funktionszeiger (bei g++ für i686 z.B. 8 Bytes statt 4).
Bei virtueller Vererbung gäbe es allerdings noch mehr Problemchen:
class CC : virtual public AA
{
public:
void f();
};
class DD : public BB, public CC
{
};
void foo(BB& bref)
{
(bref.*bf)();
}
int main()
{
BB beh;
DD deh;
foo(beh);
foo(deh);
return 0;
}
Wie soll hier der Compiler die Adresse des AA-Unterobjekts aus 'bref' in foo ermitteln?
Der Offset zwischen der Adresse des AA-Unterobjekts im BB-Objekt 'beh' und der Adresse von
'beh' ist ja nicht derselbe, wie der Offset zwischen der Adresse des AA-Unter-Unterobjekts
und der Adresse des BB-Unterobjekts des DD-Objekts 'deh'. Daher steht er nicht zur
Übersetzungszeit fest :-(
Aus diesem Grunde unterstützt der Standard die genannte Konversion im Falle von virtueller
Vererbung nicht, siehe hierzu 4.11/2.
MfG
Falk
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Kai Henning Guest
|
Posted: Fri Jun 04, 2004 6:51 am Post subject: Re: Virtuelle Ableitungen und Funktionszeiger |
|
|
Vielen Dank für die ausführliche Antwort.
Kai Henning
Falk Tannhäuser <falk.tannhauser (AT) crf (DOT) canon.fr> wrote
| Quote: | Kai Henning wrote:
Hallo,
weshalb kann die Adresse einer Methode einer
virtuell abgeleiteten Klasse nicht an ein Objekt
zugewiesen werden, welches die Adresse einer
Methode der Basisklasse speichert?
class AA
{
public:
void f();
};
class BB : virtual public AA
{
public:
void f();
};
typedef void (AA::*A_FUNC)();
A_FUNC af = &BB::f; <-- Fehlermeldung des Compilers
Wird nicht-virtuell abgeleitet ist die Zuweisung ohne Probleme
möglich. Getestet habe ich mit VC 6/7 und BCC 5.5 .
Sicher soll danach irgendwann so ein Aufruf erfolgen:
BB beh;
(beh.*af)();
(Ansonsten wäre die ganze Geschichte ja witzlos...)
Wäre die fragliche Konversion erlaubt, ginge aber auch
AA aah;
(aah.*af)();
wodurch eine BB-Methode für ein AA-Objekt, welches kein BB-Objekt ist,
aufgerufen würde.
Mit reinterpret_cast lässt sich zwar das Programm übersetzen, doch kann
man mit dem so erhaltenen Funktionszeiger nichts weiter anfangen, außer
ihn in den Originaltyp zurückzucasten; ein Versuch, die Funktion aufzurufen,
ergibt "Nicht Definiertes Verhalten" (siehe 5.2.10/6 und 5.2.10/9).
Was hingegen unter bestimmten Voraussetzungen erlaubt ist, ist die umgekehrte
Konversion:
typedef void (BB::*B_FUNC)();
B_FUNC bf = &AA::f;
da AA::f für ein BB-Objekt aufgerufen werden darf.
Die Implementierung ist allerdings nicht ganz trivial, da
- virtuelle und nicht virtuelle Funktionen verschieden behandelt werden müssen
(wenn f in AA virtuell ist, dann muss '(beh.*bf)()' BB::f aufrufen und nicht
AA::f)
- im Falle einer nicht virtuellen Funktion f der Zeiger bf nicht nur die Adresse
von f speichern muss, sondern auch die Möglichkeit bieten muss, beim Aufruf
'(beh.*bf)()' erstmal die Adresse des AA-Unterobjekts innerhalb des BB-Objekts
beh zu ermitteln, um mit dieser dann den this-Zeiger von AA::f zu initialisieren.
Hierzu reicht es, den Offset zwischen diesen beiden Adressen zu speichern, da
dieser bei nicht virtueller Vererbung schon zur Übersetzungszeit feststeht.
(Man beachte, dass diese beiden Adressen nicht notwendigerweise gleich sind,
so z.B. im Falle von Mehrfachvererbung, virtueller Vererbung, oder mit manchen
Compilern auch, wenn BB polymorph ist und AA nicht - da der V-Table-Zeiger oft
zu Beginn des Objekts im Speicher abgelegt wird).
Darum nehmen übrigens Methodenfunktionszeiger auch meist mehr Platz ein als
normale Funktionszeiger (bei g++ für i686 z.B. 8 Bytes statt 4).
Bei virtueller Vererbung gäbe es allerdings noch mehr Problemchen:
class CC : virtual public AA
{
public:
void f();
};
class DD : public BB, public CC
{
};
void foo(BB& bref)
{
(bref.*bf)();
}
int main()
{
BB beh;
DD deh;
foo(beh);
foo(deh);
return 0;
}
Wie soll hier der Compiler die Adresse des AA-Unterobjekts aus 'bref' in foo ermitteln?
Der Offset zwischen der Adresse des AA-Unterobjekts im BB-Objekt 'beh' und der Adresse von
'beh' ist ja nicht derselbe, wie der Offset zwischen der Adresse des AA-Unter-Unterobjekts
und der Adresse des BB-Unterobjekts des DD-Objekts 'deh'. Daher steht er nicht zur
Übersetzungszeit fest :-(
Aus diesem Grunde unterstützt der Standard die genannte Konversion im Falle von virtueller
Vererbung nicht, siehe hierzu 4.11/2.
MfG
Falk
|
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Heinz Saathoff Guest
|
Posted: Fri Jun 04, 2004 7:42 am Post subject: Re: Virtuelle Ableitungen und Funktionszeiger |
|
|
Falk Tannhäuser schrieb...
[snip]
| Quote: | Darum nehmen übrigens Methodenfunktionszeiger auch meist mehr Platz ein als
normale Funktionszeiger (bei g++ für i686 z.B. 8 Bytes statt 4).
|
Nicht notwendigerweise. Der DMC verwendet nur 4 Byte Zeiger. Dieser
zeigt dannauf eine vom Compiler generierte kleine Hilfsfunktion, wo dann
der eigentliche Funktionsaufruf virtual/nicht virtual durchgeführt wird.
- Heinz
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Falk Tannhäuser Guest
|
Posted: Fri Jun 04, 2004 8:32 am Post subject: Re: Virtuelle Ableitungen und Funktionszeiger |
|
|
Heinz Saathoff wrote:
| Quote: |
Falk Tannhäuser schrieb...
[snip]
Darum nehmen übrigens Methodenfunktionszeiger auch meist mehr Platz ein als
normale Funktionszeiger (bei g++ für i686 z.B. 8 Bytes statt 4).
Nicht notwendigerweise. Der DMC verwendet nur 4 Byte Zeiger. Dieser
zeigt dannauf eine vom Compiler generierte kleine Hilfsfunktion, wo dann
der eigentliche Funktionsaufruf virtual/nicht virtual durchgeführt wird.
|
Klar gibt es unterschiedliche Implementierungsmöglichkeiten.
Wie wird denn dann eigentlich das Problem der Adressadjustierung
gelöst? Ich nehme an, dass dazu die für die beiden Zuweisungen
A_FUNC af = &AA::f;
B_FUNC bf = &AA::f;
zwei verschiedene Hilfsfunktionen erzeugt werden müssen?
MfG
Falk "bloß neugierig" Tannhäuser
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Heinz Saathoff Guest
|
Posted: Fri Jun 04, 2004 1:44 pm Post subject: Re: Virtuelle Ableitungen und Funktionszeiger |
|
|
Falk Tannhäuser schrieb...
| Quote: | Klar gibt es unterschiedliche Implementierungsmöglichkeiten.
Wie wird denn dann eigentlich das Problem der Adressadjustierung
gelöst? Ich nehme an, dass dazu die für die beiden Zuweisungen
A_FUNC af = &AA::f;
B_FUNC bf = &AA::f;
zwei verschiedene Hilfsfunktionen erzeugt werden müssen?
|
Ich hab's gerade mal probiert. Ohne virtuelle Ableitung werden gar keine
Hilfsfunktionen generiert.
Wenn AA:f nicht virtuell ist, wird in af und bf die Adresse von f
gespeichert.
Ist AA:f virtuell, generiert der Compiler ein Codestück, das aus der
vtable die wirkliche Adresse bestimmt und zu dieser springt (2
Instruktionen). In af und bf wird die Adresse des Codestückchens
gespeichert. Adressanpassungen sind nicht notwendig.
Wenn allerdings virtuell abgeleitet wird, läßt der Comiler die Zeile
B_FUNC bf = &AA:f;
nicht zu (Meldung: illegal cast). Wahrscheinlich deshalb, weil bei
virtueller Ableitung der BB-Teil nicht mehr unmittelbar dem AA-Teil
folgen muß.
- Heinz
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Falk Tannhäuser Guest
|
Posted: Fri Jun 04, 2004 4:08 pm Post subject: Re: Virtuelle Ableitungen und Funktionszeiger |
|
|
Heinz Saathoff wrote:
| Quote: |
Falk Tannhäuser schrieb...
Klar gibt es unterschiedliche Implementierungsmöglichkeiten.
Wie wird denn dann eigentlich das Problem der Adressadjustierung
gelöst? Ich nehme an, dass dazu die für die beiden Zuweisungen
A_FUNC af = &AA::f;
B_FUNC bf = &AA::f;
zwei verschiedene Hilfsfunktionen erzeugt werden müssen?
Ich hab's gerade mal probiert. Ohne virtuelle Ableitung werden gar keine
Hilfsfunktionen generiert.
Wenn AA:f nicht virtuell ist, wird in af und bf die Adresse von f
gespeichert.
Ist AA:f virtuell, generiert der Compiler ein Codestück, das aus der
vtable die wirkliche Adresse bestimmt und zu dieser springt (2
Instruktionen). In af und bf wird die Adresse des Codestückchens
gespeichert. Adressanpassungen sind nicht notwendig.
Bei Einfachvererbung oft nicht. |
Bei Mehrfachvererbung (insbesondere wenn die Basisklassen nicht leer sind),
selbst ohne dass virtuelle Vererbung ins Spiel kommt, sollte eigentlich
immer eine Adressanpassung für wenigstens eine der Basisklassen erforderlich
sein - bei g++ stimmen dann nur die Anfangsadressen des kompletten Objekts
und desjenigen Basisklassen-Unterobjekts überein, dessen Basisklasse als
erstes in der Basisklassenliste der Klassendefinition steht.
D.h. mit
class nochnAA { int dummy; };
class BB : public nochnAA, public AA { ... };
BB beh;
ist
static_cast<void*>(&beh) != static_cast<void*>(static_cast<AA*>(&beh))
Bei nicht virtuellem 'f' in AA und BB muss dann zur Laufzeit hier
A_FUNC af = &BB::f; // 1
(beh.*af)();
...
af = &AA::f; // 2
(beh.*af)();
beim ersten Aufruf die Adresse von 'beh' in den this-Zeiger für BB::f übergeben
werden, während beim zweiten Aufruf die Adresse des AA-Unterobjekts übergeben
werden muss. Dies lässt sich sowohl mit der g++-Methode bewerkstelligen
(wo der Zeiger den Adressoffset enthält) als auch mit der Hilfsfunktionenmethode.
| Quote: |
Wenn allerdings virtuell abgeleitet wird, läßt der Compiler die Zeile
B_FUNC bf = &AA:f;
nicht zu (Meldung: illegal cast). Wahrscheinlich deshalb, weil bei
virtueller Ableitung der BB-Teil nicht mehr unmittelbar dem AA-Teil
folgen muß.
Joh. Und nicht nur das (dieses wäre ja auch schon bei nichtvirtueller |
Dreifachvererbung der Fall) - sondern der Abstand zwischen beiden steht
nicht mal zur Übersetzungszeit fest. Drum versagt die g++-Methode. Mit
der Hilfsfunktionenmethode sollte sich theoretisch was g'scheit's machen
lassen (mittels nachgucken in der V-Table) - doch der Standard sagt in
4.11/2 "njet".
MfG
Falk
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Mon Jun 07, 2004 2:10 pm Post subject: Re: Virtuelle Ableitungen und Funktionszeiger |
|
|
Falk Tannhäuser <falk.tannhauser (AT) crf (DOT) canon.fr> wrote
| Quote: | Heinz Saathoff wrote:
Falk Tannhäuser schrieb...
Klar gibt es unterschiedliche Implementierungsmöglichkeiten.
Wie wird denn dann eigentlich das Problem der Adressadjustierung
gelöst? Ich nehme an, dass dazu die für die beiden Zuweisungen
A_FUNC af = &AA::f;
B_FUNC bf = &AA::f;
zwei verschiedene Hilfsfunktionen erzeugt werden müssen?
Ich hab's gerade mal probiert. Ohne virtuelle Ableitung werden gar
keine Hilfsfunktionen generiert. Wenn AA:f nicht virtuell ist, wird
in af und bf die Adresse von f gespeichert. Ist AA:f virtuell,
generiert der Compiler ein Codestück, das aus der vtable die
wirkliche Adresse bestimmt und zu dieser springt (2
Instruktionen). In af und bf wird die Adresse des Codestückchens
gespeichert. Adressanpassungen sind nicht notwendig.
Bei Einfachvererbung oft nicht.
|
Ist aber egal. Grob genommen, das Stückchen, das der Compiler generiert,
entspricht einfach einer nicht virtuellen Funktion der entsprechenden
Klasse, die die virtuelle Function aufruft. Nur mit einem jmp-Befehl
statt einem call. Beim Aufruf einer virtuellen Funktion muss haüfig den
this-Zeiger korregiert.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|