C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

this in Initialisierungsliste

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German)
View previous topic :: View next topic  
Author Message
Sebastian Pfützner
Guest





PostPosted: Mon Mar 20, 2006 3:56 pm    Post subject: this in Initialisierungsliste Reply with quote



Hallo Gruppe,
ist es vom Standard her erlaubt, den this-Pointer in der
Initialisierungsliste zu dereferenzieren, aber sonst nicht anderweitig
zu verwenden? Hierzu folgender Code:

struct B;

struct A
{
A(const B& b): m_b(b) {}
const B& m_b;
};

struct B
{
B(): m_a(*this) {}
A m_a;
};

int main()
{
B b;
}

Falls dies nicht erlaubt ist, darf ich dem Konstruktor von A den
this-Pointer wenigstens direkt übergeben und in A speichern? In beiden
Fällen generiert der vc++ Compiler eine Warnung, die mich etwas irritiert:

"warning C4355: this': wird in Initialisierungslisten für Basisklasse
verwendet"

Ist es eigentlich üblich, wenn ein Memberobjekt eine Referenz auf seinen
"Halter" speichert und benutzt oder gibt es da bessere Möglichkeiten?

vielen Dank im Voraus...
--
Sebastian Pfützner
s.pfuetzner (AT) onlinehome (DOT) de
ICQ-ID: 39965036

--
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





PostPosted: Tue Mar 21, 2006 1:06 am    Post subject: Re: this in Initialisierungsliste Reply with quote



Sebastian Pfützner wrote:

Quote:
Hallo Gruppe,
ist es vom Standard her erlaubt, den this-Pointer in der
Initialisierungsliste zu dereferenzieren, aber sonst nicht anderweitig
zu verwenden? Hierzu folgender Code:

struct B;

struct A
{
A(const B& b): m_b(b) {}
const B& m_b;
};

struct B
{
B(): m_a(*this) {}
A m_a;
};

int main()
{
B b;
}

Falls dies nicht erlaubt ist, darf ich dem Konstruktor von A den
this-Pointer wenigstens direkt übergeben und in A speichern?

Mit dem Zeiger geht das jeden Fall in Ordnung. Bei der Referenz bin ich mir
nicht ganz sicher. Der this-Zeiger wird dabei zwar dereferenziert, aber der
Wert meines Erachtens nicht genutzt, was zumindest in manchen Fällen auch
bei uninitailisierten Objekten erlaubt ist (z.B. wäre int* x; sizeof(*x);
erlaubt, da sizeof den Wert nicht benutzt - ich weiß nur nicht, ob das für
die Referenz auch so gilt).

Quote:
Ist es eigentlich üblich, wenn ein Memberobjekt eine Referenz auf seinen
"Halter" speichert und benutzt oder gibt es da bessere Möglichkeiten?

Wenn das Memberobjekt seinen Halter denn kennen muß. Aber da frage ich mich,
warum es dann überhaupt ein Member ist. A wird ja dadurch abhängig von B.
Damit hast du Abhängigkeiten über Kreuz, was selten gut ist, und du kannst
A nicht mehr unabhängig von B benutzen.

--
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
Torsten Robitzki
Guest





PostPosted: Tue Mar 21, 2006 11:06 pm    Post subject: Re: this in Initialisierungsliste Reply with quote



Rolf Magnus wrote:

Quote:
Sebastian Pfützner wrote:


Hallo Gruppe,
ist es vom Standard her erlaubt, den this-Pointer in der
Initialisierungsliste zu dereferenzieren, aber sonst nicht anderweitig
zu verwenden? Hierzu folgender Code:

struct B;

struct A
{
A(const B& b): m_b(b) {}
const B& m_b;
};

struct B
{
B(): m_a(*this) {}
A m_a;
};

int main()
{
B b;
}

Falls dies nicht erlaubt ist, darf ich dem Konstruktor von A den
this-Pointer wenigstens direkt übergeben und in A speichern?


Mit dem Zeiger geht das jeden Fall in Ordnung. Bei der Referenz bin ich mir
nicht ganz sicher. Der this-Zeiger wird dabei zwar dereferenziert, aber der
Wert meines Erachtens nicht genutzt, was zumindest in manchen Fällen auch
bei uninitailisierten Objekten erlaubt ist (z.B. wäre int* x; sizeof(*x);
erlaubt, da sizeof den Wert nicht benutzt - ich weiß nur nicht, ob das für
die Referenz auch so gilt).

Der Unterschied ist, das bei sizeof(*x) garantiert ist, das der Ausdruck
nicht ausgewertet wird. Bei einer Referenz muß der Ausdruck zur Laufzeit
ausgewertet werden (und würde dann zu undefiniertem Verhalten führen).

mfg Torsten

--
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
Andre Poenitz
Guest





PostPosted: Wed Mar 22, 2006 1:29 am    Post subject: Re: this in Initialisierungsliste Reply with quote

Rolf Magnus <ramagnus@t-online.de> wrote:
Quote:
Mit dem Zeiger geht das jeden Fall in Ordnung. Bei der Referenz bin ich mir
nicht ganz sicher. Der this-Zeiger wird dabei zwar dereferenziert, aber der
Wert meines Erachtens nicht genutzt, was zumindest in manchen Fällen auch
bei uninitailisierten Objekten erlaubt ist (z.B. wäre int* x; sizeof(*x);
erlaubt, da sizeof den Wert nicht benutzt - ich weiß nur nicht, ob das für
die Referenz auch so gilt).

Mir war so, asl ob 'sizeof' hier eine Extrawurst gebraten bekommt. Habe
aber den Standard im Moment nicht zur Hand.

Andre'

--
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
Guest





PostPosted: Wed Mar 22, 2006 2:06 pm    Post subject: Re: this in Initialisierungsliste Reply with quote

Sebastian Pfützner wrote:

Quote:
ist es vom Standard her erlaubt, den this-Pointer in der
Initialisierungsliste zu dereferenzieren, aber sonst nicht
anderweitig zu verwenden? Hierzu folgender Code:

struct B;

struct A
{
A(const B& b): m_b(b) {}
const B& m_b;
};

struct B
{
B(): m_a(*this) {}
A m_a;
};

int main()
{
B b;
}

Es soll gehen. Der Speicher des Objektes ist schon allokiert;
der Zeiger selber ist also gültig. Der Ausdruck *this bildet
einen l-Value, der auf diesen Speicher bezieht. Das Objekt
selbe existiert wohl noch nicht, aber, laut §3.8/6:

Similarly, before the lifetime of an object has started but
after the storage which the object will occupy habe been
allocated or, after the lifetime of an object has ended and
before the storage which the object occupied is reused or
released, and lvalue which refers to the original object
[also hier, *this] may be used but only in limited ways.
Such an lvalue refers to allocated storage, and using the
properties of the lvalue which do not repend on its value is
well defined. If an lvalue-to-rvalue conversion is applied
to such an lvalue, the program has undefined behavior; if
the origihnal object will be or was of a non-POD class type,
the program has undefined behavior if:

-- the lvalue is used to access a non-static data member or
call a non-static member function of the object, or

-- the lvalue is implicitly converted to a reference to a
base class type, or

-- the lvalue is used as the operand of a static_cast
(except when the conversion is ultimately to char$ or
unsigned char&), or

-- the lvalue is used as the operand of a dynamic_cast or
as the operand of typeid.

Der genaue Code oben also geht. Vorsicht aber mit dem zweiten
Punkt. Hast du eine abgeleitete Klasse C:

struct C : B
{
A m_a ;
C(): m_a( *this ) {}
} ;

dann geht es nicht (und auch nicht wenn du Zeiger benutzt -- der
vorherige Absatz sagt ungefähr dieselbe für Zieger).

Quote:
Falls dies nicht erlaubt ist, darf ich dem Konstruktor von A
den this-Pointer wenigstens direkt übergeben und in A
speichern? In beiden Fällen generiert der vc++ Compiler eine
Warnung, die mich etwas irritiert:

"warning C4355: this': wird in Initialisierungslisten für Basisklasse
verwendet"

Ein Compiler darf über allem warnen, was er will. Und freilich
muss man hier vorsichtig sein; A darf recht wenig mit dem Zeiger
bzw. der Referenz tun. Wenn die zwei Klassen eng verbunden und
zusammen entwickelt werden, sehe ich nichts dagegen. In anderem
Fallen aber würde ich es nur wagen, wenn die Klasse A
ausdrucklich dokumentiert, dass es gehen soll.

Quote:
Ist es eigentlich üblich, wenn ein Memberobjekt eine Referenz
auf seinen "Halter" speichert und benutzt oder gibt es da
bessere Möglichkeiten?

M.E. ist es nicht üblich, dass Memberobjekte Zeiger auf ihren
Halter enthalten:-). Das Problem kommt aber auch vor, wenn man
das Strategie-Muster benutzt, und die Strategie selbe als
Komponent einer abgeleiteten Klasse haben will. Dann aber
funktionniert es nicht; man muss sondere Zwischenstuffe
einrichten.

--
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
Jörg Barfurth
Guest





PostPosted: Thu Mar 23, 2006 9:06 am    Post subject: Re: this in Initialisierungsliste Reply with quote

kanze schrieb:
Quote:
Sebastian Pfützner wrote:

ist es vom Standard her erlaubt, den this-Pointer in der
Initialisierungsliste zu dereferenzieren, aber sonst nicht
anderweitig zu verwenden? Hierzu folgender Code:


Es soll gehen. Der Speicher des Objektes ist schon allokiert;
der Zeiger selber ist also gültig. Der Ausdruck *this bildet
einen l-Value, der auf diesen Speicher bezieht. Das Objekt
selbe existiert wohl noch nicht, aber, laut §3.8/6:

Similarly, before the lifetime of an object has started but
after the storage which the object will occupy habe been
allocated or, after the lifetime of an object has ended and
before the storage which the object occupied is reused or
released, and lvalue which refers to the original object
[also hier, *this] may be used but only in limited ways.
Such an lvalue refers to allocated storage, and using the
properties of the lvalue which do not repend on its value is
well defined. If an lvalue-to-rvalue conversion is applied
to such an lvalue, the program has undefined behavior; if
the origihnal object will be or was of a non-POD class type,
the program has undefined behavior if:

-- the lvalue is used to access a non-static data member or
call a non-static member function of the object, or

-- the lvalue is implicitly converted to a reference to a
base class type, or


[...]

Das ist aber noch nicht alles. Während des Konstruierens gelten noch
weitere Regeln, die in 12.6.2 und 12.7 beschrieben sind. Sonst dürfte
man sogar im Konstruktorrumpf keine Member verwenden ...

Quote:
Der genaue Code oben also geht. Vorsicht aber mit dem zweiten
Punkt. Hast du eine abgeleitete Klasse C:

struct C : B
{
A m_a ;
C(): m_a( *this ) {}
} ;

dann geht es nicht (und auch nicht wenn du Zeiger benutzt -- der
vorherige Absatz sagt ungefähr dieselbe für Zieger).


Doch, das geht. 12.7/2 sagt:

To explicitly or implicitly convert a pointer (an lvalue) referring
to an object of class X to a pointer (reference) to a direct or
indirect base class B of X, the construction of X and the construction
of all of its direct or indirect bases that directly or indirectly
derive from B shall have started [...]

Wenn Member konstruiert werden, dann sind alle Basisklassen bereits
fertig konstruiert, so dass die Konvertierung von this in einen
Basisklassenzeiger (oder von *this in eine Basisklassenreferenz)
zulässig ist. Bei Initialisierern von Basisklassen muss man vorsichtiger
sein und die Initialisierungsreihenfolge beachten.

Gruss, Jörg

--
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
Guest





PostPosted: Thu Mar 23, 2006 1:06 pm    Post subject: Re: this in Initialisierungsliste Reply with quote

Jörg Barfurth wrote:
Quote:
kanze schrieb:
Sebastian Pfützner wrote:

ist es vom Standard her erlaubt, den this-Pointer in der
Initialisierungsliste zu dereferenzieren, aber sonst nicht
anderweitig zu verwenden? Hierzu folgender Code:

Es soll gehen. Der Speicher des Objektes ist schon
allokiert; der Zeiger selber ist also gültig. Der Ausdruck
*this bildet einen l-Value, der auf diesen Speicher bezieht.
Das Objekt selbe existiert wohl noch nicht, aber, laut
§3.8/6:

Similarly, before the lifetime of an object has started but
after the storage which the object will occupy habe been
allocated or, after the lifetime of an object has ended and
before the storage which the object occupied is reused or
released, and lvalue which refers to the original object
[also hier, *this] may be used but only in limited ways.
Such an lvalue refers to allocated storage, and using the
properties of the lvalue which do not repend on its value is
well defined. If an lvalue-to-rvalue conversion is applied
to such an lvalue, the program has undefined behavior; if
the origihnal object will be or was of a non-POD class type,
the program has undefined behavior if:

-- the lvalue is used to access a non-static data member or
call a non-static member function of the object, or

-- the lvalue is implicitly converted to a reference to a
base class type, or

[...]

Das ist aber noch nicht alles. Während des Konstruierens
gelten noch weitere Regeln, die in 12.6.2 und 12.7 beschrieben
sind. Sonst dürfte man sogar im Konstruktorrumpf keine Member
verwenden ...

Die habe ich tatsächlich übersehen. Es gibt also einen
Widerspruch hier -- weil §3.8/5 (für Zeiger) und §3.8/6 (für
Referenzen) sagen ausdrucklich, dass es nicht geht. (Und wie du
sagst, das gilt auch im Konstruktorrumpf, wenn man es
wortwörtlich nimmt.)

Quote:
Der genaue Code oben also geht. Vorsicht aber mit dem zweiten
Punkt. Hast du eine abgeleitete Klasse C:

struct C : B
{
A m_a ;
C(): m_a( *this ) {}
} ;

dann geht es nicht (und auch nicht wenn du Zeiger benutzt -- der
vorherige Absatz sagt ungefähr dieselbe für Zieger).

Doch, das geht. 12.7/2 sagt:

To explicitly or implicitly convert a pointer (an lvalue) referring
to an object of class X to a pointer (reference) to a direct or
indirect base class B of X, the construction of X and the construction
of all of its direct or indirect bases that directly or indirectly
derive from B shall have started [...]

Wenn Member konstruiert werden, dann sind alle Basisklassen
bereits fertig konstruiert, so dass die Konvertierung von this
in einen Basisklassenzeiger (oder von *this in eine
Basisklassenreferenz) zulässig ist. Bei Initialisierern von
Basisklassen muss man vorsichtiger sein und die
Initialisierungsreihenfolge beachten.

Interessant. In der Tat, im Fall, wo ich Probleme gehabt habe,
ging es ehe um eine Basisklasse, also :

class MyIStream : private MyStreambuf, public std::istream
{
public:
MyIStream() : std::istream( this ) {}
// MyStreambuf wird von std::streambuf abgeleitet.
} ;

Erbt man virtuell von MyStreambuf, dann bekomment std::istream
einen falschen Zeiger, mindestens mit Sun CC. Was mir eigentlich
ein bisschen erstaunt hat, weil MyStreambuf wohl die richtige
Adresse als this bekommen hat. (Nach Überlegen verstehe ich,
warum das so ist. Ich muss aber sagen, dass es mir überrascht
hat, als ich darauf gestossen bin.)

Immerhin bin ich nicht sicher. In meinem vorherigen Beispiel,
hat die Construction von C angefangen, wenn ich *this als
Parameter übergebe? Oder wird es erst als angefangen betrachtet,
wenn ich in den Konstruktorrumpf eintrete?

--
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
Heinz Saathoff
Guest





PostPosted: Thu Mar 23, 2006 1:06 pm    Post subject: Re: this in Initialisierungsliste Reply with quote

Moin,

Andre Poenitz schrieb...
Quote:
Rolf Magnus <ramagnus@t-online.de> wrote:
Mit dem Zeiger geht das jeden Fall in Ordnung. Bei der Referenz bin ich mir
nicht ganz sicher. Der this-Zeiger wird dabei zwar dereferenziert, aber der
Wert meines Erachtens nicht genutzt, was zumindest in manchen FÃ=3Fllen auch
bei uninitailisierten Objekten erlaubt ist (z.B. wÃ=3Fre int* x; sizeof(*x);
erlaubt, da sizeof den Wert nicht benutzt - ich weiþ nur nicht, ob das fÃ=3Fr
die Referenz auch so gilt).

Mir war so, asl ob 'sizeof' hier eine Extrawurst gebraten bekommt.

Soweit ich mich erinnere, wird sizeof _immer_ zur Compilezeit berechnet.
Im Compilat steht deshalb anstelle des sizeof-Ausdrucks eine vom
Compiler anhand statischer Typauswertung bestimmte Konstante.


- 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
Marcel Müller
Guest





PostPosted: Thu Mar 23, 2006 2:06 pm    Post subject: Re: this in Initialisierungsliste Reply with quote

Hallo!

Jörg Barfurth schrieb:
Quote:
Wenn Member konstruiert werden, dann sind alle Basisklassen bereits
fertig konstruiert, so dass die Konvertierung von this in einen
Basisklassenzeiger (oder von *this in eine Basisklassenreferenz)
zulässig ist. Bei Initialisierern von Basisklassen muss man vorsichtiger
sein und die Initialisierungsreihenfolge beachten.

Der Vollständigkeit halber sei noch angemerkt, dass man bei solchen
Spielchen ruck zuck mal ein "virtual pure function called" bekommt. Da
das Objekt bis zum Abschluss des eigenen Konstruktors noch vom Typ der
Basisklasse ist. Und wenn die Basisklasse abstrakt ist, hat man es
temporär mit einer existierenden Instanz einer abstrakten Klasse zu tun.


Marcel

--
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
Thomas Mang
Guest





PostPosted: Fri Mar 24, 2006 12:06 pm    Post subject: Re: this in Initialisierungsliste Reply with quote

"kanze" <kanze@gabi-soft.fr> schrieb im Newsbeitrag
news:1143118363.447007.263570 (AT) v46g2000cwv (DOT) googlegroups.com...

Quote:

Immerhin bin ich nicht sicher. In meinem vorherigen Beispiel,
hat die Construction von C angefangen, wenn ich *this als
Parameter übergebe? Oder wird es erst als angefangen betrachtet,
wenn ich in den Konstruktorrumpf eintrete?


Ich bin über das schon vor einiger Zeit drübergestolpert, und habe nirgends
definiert gefunden wann ein Konstruktor beginnt - also mit Eintritt in die
Initialisierungsliste, oder in den Rumpf.
Gemäß dem Beispiel in 12.7/2 dürfte es aber mit Eintritt in die
Initialisierungsliste sein (ich weiß aber schon, examples are
non-normative...)

Lustig ist auch, dass in 3.8 nur von undefiniertem Verhalten bei
_impliziten_ Konvertierungen gesprochen wird. Rein paragraphenjuristisch
gesehen sollte man alle Probleme umgehen, können, indem man eine
cast-expression wie in 5.4 [ (T) cast-expression ] einsetzt....


Thomas


--
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
Jörg Barfurth
Guest





PostPosted: Fri Mar 24, 2006 11:06 pm    Post subject: Re: this in Initialisierungsliste Reply with quote

Thomas Mang schrieb:

Quote:
Lustig ist auch, dass in 3.8 nur von undefiniertem Verhalten bei
_impliziten_ Konvertierungen gesprochen wird. Rein paragraphenjuristisch
gesehen sollte man alle Probleme umgehen, können, indem man eine
cast-expression wie in 5.4 [ (T) cast-expression ] einsetzt....


Nein. Das mit den impliziten Konvertierungen ist nur ein Punkt in der
Liste. Laut dem nächsten Punkt ist das Verhalten aber auch undefiniert, wenn

- the pointer is used as the operand of a static_cast (5.2.9) (except
when the conversion is to void*, or to void* and subsequently to char*,
or unsigned char*)

Analoges gibt es dann auch für L-values und Referenzen.

(Ein C-style cast ist in den betreffenden Fällen bedeutungsgleich mit
einem static_cast.)

Ciao, Jörg

--
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
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German) All times are GMT
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.