Comment eviter le warning (sous VC6)
Comment eviter le warning (sous VC6)
Comment eviter le warning (sous VC6)
Comment eviter le warning (sous VC6)
#pragma warning(disable: 4355)
Comment eviter le warning (sous VC6)
#pragma warning(disable: 4355)
Comment eviter le warning (sous VC6)
#pragma warning(disable: 4355)
class B
{
public:
B(class A* pA) : m_pA(pA) {}
private:
class A* m_pA;
C'est quoi exactement, ce truc ? Avec "typename" j'aurais compris,
mais tel quel, je ne vois pas à quoi ça correspond.
Ecrire class A; avant c'est pareil que redire que A est une classe à
chaque fois (ou typename, c'est kifkif) (plus lourd, peut etre, mais
là l'est pas mon pb !) Mon pb, c'est de savoir si oui ou non il est
risqué (ou non portable) d'utiliser 'this' dans la liste
d'initialisation des membres.
class B
{
public:
B(class A* pA) : m_pA(pA) {}
private:
class A* m_pA;
C'est quoi exactement, ce truc ? Avec "typename" j'aurais compris,
mais tel quel, je ne vois pas à quoi ça correspond.
Ecrire class A; avant c'est pareil que redire que A est une classe à
chaque fois (ou typename, c'est kifkif) (plus lourd, peut etre, mais
là l'est pas mon pb !) Mon pb, c'est de savoir si oui ou non il est
risqué (ou non portable) d'utiliser 'this' dans la liste
d'initialisation des membres.
class B
{
public:
B(class A* pA) : m_pA(pA) {}
private:
class A* m_pA;
C'est quoi exactement, ce truc ? Avec "typename" j'aurais compris,
mais tel quel, je ne vois pas à quoi ça correspond.
Ecrire class A; avant c'est pareil que redire que A est une classe à
chaque fois (ou typename, c'est kifkif) (plus lourd, peut etre, mais
là l'est pas mon pb !) Mon pb, c'est de savoir si oui ou non il est
risqué (ou non portable) d'utiliser 'this' dans la liste
d'initialisation des membres.
class B
{
public:
B(class A* pA) : m_pA(pA) {}
private:
class A* m_pA;
C'est quoi exactement, ce truc ? Avec "typename" j'aurais compris,
mais tel quel, je ne vois pas à quoi ça correspond.
Ecrire class A; avant c'est pareil que redire que A est une classe à
chaque fois (ou typename, c'est kifkif) (plus lourd, peut etre, mais
là l'est pas mon pb !) Mon pb, c'est de savoir si oui ou non il est
risqué (ou non portable) d'utiliser 'this' dans la liste
d'initialisation des membres.
cat fclc++.cc
#include <iostream>
g++ --version
g++ (GCC) 3.2 20020818 (prerelease)
g++ -o fclc++ fclc++.cc -Wall -ansi -pedantic
./fclc++
0x76fd54 0x76fd54
class B
{
public:
B(class A* pA) : m_pA(pA) {}
private:
class A* m_pA;
C'est quoi exactement, ce truc ? Avec "typename" j'aurais compris,
mais tel quel, je ne vois pas à quoi ça correspond.
Ecrire class A; avant c'est pareil que redire que A est une classe à
chaque fois (ou typename, c'est kifkif) (plus lourd, peut etre, mais
là l'est pas mon pb !) Mon pb, c'est de savoir si oui ou non il est
risqué (ou non portable) d'utiliser 'this' dans la liste
d'initialisation des membres.
cat fclc++.cc
#include <iostream>
g++ --version
g++ (GCC) 3.2 20020818 (prerelease)
g++ -o fclc++ fclc++.cc -Wall -ansi -pedantic
./fclc++
0x76fd54 0x76fd54
class B
{
public:
B(class A* pA) : m_pA(pA) {}
private:
class A* m_pA;
C'est quoi exactement, ce truc ? Avec "typename" j'aurais compris,
mais tel quel, je ne vois pas à quoi ça correspond.
Ecrire class A; avant c'est pareil que redire que A est une classe à
chaque fois (ou typename, c'est kifkif) (plus lourd, peut etre, mais
là l'est pas mon pb !) Mon pb, c'est de savoir si oui ou non il est
risqué (ou non portable) d'utiliser 'this' dans la liste
d'initialisation des membres.
cat fclc++.cc
#include <iostream>
g++ --version
g++ (GCC) 3.2 20020818 (prerelease)
g++ -o fclc++ fclc++.cc -Wall -ansi -pedantic
./fclc++
0x76fd54 0x76fd54
"amerio" writes:class B
{
public:
B(class A* pA) : m_pA(pA) {}
private:
class A* m_pA;
C'est quoi exactement, ce truc ? Avec "typename" j'aurais compris,
mais tel quel, je ne vois pas à quoi ça correspond.
Ecrire class A; avant c'est pareil que redire que A est une classe à
chaque fois (ou typename, c'est kifkif) (plus lourd, peut etre, mais
là l'est pas mon pb !) Mon pb, c'est de savoir si oui ou non il est
risqué (ou non portable) d'utiliser 'this' dans la liste
d'initialisation des membres.
J'ajouterais que le code suivant compile parfaitement sous GCC, sans
diagnostique :
cat fclc++.cc
#include <iostream>
class B
{
public:
B( class A* pA ) : m_pA( pA ) { }
class A* m_pA ;
} ;
class A
{
public:
A() : m_B( this ) { }
const B m_B ;
} ;
int main()
{
A a ;
std::cout << a.m_B.m_pA << ' ' << & a << std::endl ;
return 0 ;
}g++ --version
g++ (GCC) 3.2 20020818 (prerelease)
Copyright (C) 2002 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.g++ -o fclc++ fclc++.cc -Wall -ansi -pedantic
./fclc++
0x76fd54 0x76fd54
"amerio" <amerio@hotmail.com> writes:
class B
{
public:
B(class A* pA) : m_pA(pA) {}
private:
class A* m_pA;
C'est quoi exactement, ce truc ? Avec "typename" j'aurais compris,
mais tel quel, je ne vois pas à quoi ça correspond.
Ecrire class A; avant c'est pareil que redire que A est une classe à
chaque fois (ou typename, c'est kifkif) (plus lourd, peut etre, mais
là l'est pas mon pb !) Mon pb, c'est de savoir si oui ou non il est
risqué (ou non portable) d'utiliser 'this' dans la liste
d'initialisation des membres.
J'ajouterais que le code suivant compile parfaitement sous GCC, sans
diagnostique :
cat fclc++.cc
#include <iostream>
class B
{
public:
B( class A* pA ) : m_pA( pA ) { }
class A* m_pA ;
} ;
class A
{
public:
A() : m_B( this ) { }
const B m_B ;
} ;
int main()
{
A a ;
std::cout << a.m_B.m_pA << ' ' << & a << std::endl ;
return 0 ;
}
g++ --version
g++ (GCC) 3.2 20020818 (prerelease)
Copyright (C) 2002 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.
g++ -o fclc++ fclc++.cc -Wall -ansi -pedantic
./fclc++
0x76fd54 0x76fd54
"amerio" writes:class B
{
public:
B(class A* pA) : m_pA(pA) {}
private:
class A* m_pA;
C'est quoi exactement, ce truc ? Avec "typename" j'aurais compris,
mais tel quel, je ne vois pas à quoi ça correspond.
Ecrire class A; avant c'est pareil que redire que A est une classe à
chaque fois (ou typename, c'est kifkif) (plus lourd, peut etre, mais
là l'est pas mon pb !) Mon pb, c'est de savoir si oui ou non il est
risqué (ou non portable) d'utiliser 'this' dans la liste
d'initialisation des membres.
J'ajouterais que le code suivant compile parfaitement sous GCC, sans
diagnostique :
cat fclc++.cc
#include <iostream>
class B
{
public:
B( class A* pA ) : m_pA( pA ) { }
class A* m_pA ;
} ;
class A
{
public:
A() : m_B( this ) { }
const B m_B ;
} ;
int main()
{
A a ;
std::cout << a.m_B.m_pA << ' ' << & a << std::endl ;
return 0 ;
}g++ --version
g++ (GCC) 3.2 20020818 (prerelease)
Copyright (C) 2002 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.g++ -o fclc++ fclc++.cc -Wall -ansi -pedantic
./fclc++
0x76fd54 0x76fd54
drkm wrote in message
news:...J'ajouterais que le code suivant compile parfaitement sous GCC,
sans diagnostique :
Et pourtant, ce n'est pas légal:-).cat fclc++.cc
#include <iostream>
Tu as oublié l'« #include <ostream> ». Les opérateurs << ne sont pas
définis.
class B
{
public:
B( class A* pA ) : m_pA( pA ) { }
class A* m_pA ;
} ;
class A
{
public:
A() : m_B( this ) { }
const B m_B ;
} ;
Ajoutons un:
class C : public A
{
public:
C() : unDeuxiemeB( this ) {}
B const unDeuxiemeB ;
} ;
G++ ne dit toujours rien. Et pourtant, c'est illégal. La conversion
de this (un C*) en A* a un comportement indéfini.
En fait, il y a de fortes chances que ça marche, tant qu'il n'y a
pas d'héritage virtuel. Mais la norme l'interdit explicitement.
int main()
{
A a ;
std::cout << a.m_B.m_pA << ' ' << & a << std::endl ;
return 0 ;
}g++ --version
g++ (GCC) 3.2 20020818 (prerelease)
Copyright (C) 2002 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.g++ -o fclc++ fclc++.cc -Wall -ansi -pedantic
./fclc++
0x76fd54 0x76fd54
Le fait que quelque chose marche avec un compilateur donné ne prouve
pas qu'il soit légal. Dans le cas en question, c'est légal, mais
seulement parce que le constructeur qui a reçu le paramètre ne fait
que le copier. Changer ce constructeur, g++ ne râlera toujours pas,
mais le code ne serait plus correct.
drkm <darkman_spam@yahoo.fr> wrote in message
news:<wkisqcu0mm.fsf@yahoo.fr>...
J'ajouterais que le code suivant compile parfaitement sous GCC,
sans diagnostique :
Et pourtant, ce n'est pas légal:-).
cat fclc++.cc
#include <iostream>
Tu as oublié l'« #include <ostream> ». Les opérateurs << ne sont pas
définis.
class B
{
public:
B( class A* pA ) : m_pA( pA ) { }
class A* m_pA ;
} ;
class A
{
public:
A() : m_B( this ) { }
const B m_B ;
} ;
Ajoutons un:
class C : public A
{
public:
C() : unDeuxiemeB( this ) {}
B const unDeuxiemeB ;
} ;
G++ ne dit toujours rien. Et pourtant, c'est illégal. La conversion
de this (un C*) en A* a un comportement indéfini.
En fait, il y a de fortes chances que ça marche, tant qu'il n'y a
pas d'héritage virtuel. Mais la norme l'interdit explicitement.
int main()
{
A a ;
std::cout << a.m_B.m_pA << ' ' << & a << std::endl ;
return 0 ;
}
g++ --version
g++ (GCC) 3.2 20020818 (prerelease)
Copyright (C) 2002 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.
g++ -o fclc++ fclc++.cc -Wall -ansi -pedantic
./fclc++
0x76fd54 0x76fd54
Le fait que quelque chose marche avec un compilateur donné ne prouve
pas qu'il soit légal. Dans le cas en question, c'est légal, mais
seulement parce que le constructeur qui a reçu le paramètre ne fait
que le copier. Changer ce constructeur, g++ ne râlera toujours pas,
mais le code ne serait plus correct.
drkm wrote in message
news:...J'ajouterais que le code suivant compile parfaitement sous GCC,
sans diagnostique :
Et pourtant, ce n'est pas légal:-).cat fclc++.cc
#include <iostream>
Tu as oublié l'« #include <ostream> ». Les opérateurs << ne sont pas
définis.
class B
{
public:
B( class A* pA ) : m_pA( pA ) { }
class A* m_pA ;
} ;
class A
{
public:
A() : m_B( this ) { }
const B m_B ;
} ;
Ajoutons un:
class C : public A
{
public:
C() : unDeuxiemeB( this ) {}
B const unDeuxiemeB ;
} ;
G++ ne dit toujours rien. Et pourtant, c'est illégal. La conversion
de this (un C*) en A* a un comportement indéfini.
En fait, il y a de fortes chances que ça marche, tant qu'il n'y a
pas d'héritage virtuel. Mais la norme l'interdit explicitement.
int main()
{
A a ;
std::cout << a.m_B.m_pA << ' ' << & a << std::endl ;
return 0 ;
}g++ --version
g++ (GCC) 3.2 20020818 (prerelease)
Copyright (C) 2002 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.g++ -o fclc++ fclc++.cc -Wall -ansi -pedantic
./fclc++
0x76fd54 0x76fd54
Le fait que quelque chose marche avec un compilateur donné ne prouve
pas qu'il soit légal. Dans le cas en question, c'est légal, mais
seulement parce que le constructeur qui a reçu le paramètre ne fait
que le copier. Changer ce constructeur, g++ ne râlera toujours pas,
mais le code ne serait plus correct.
drkm wrote in message
news:...En même temps, en cherchant un peu dans la norme, j'ai trouvé
ceci :
9.3.2/1
In the body of a nonstatic (9.3) member function, the keyword
`this´ is a non-lvalue expression whose value is the address
of the object for which the function is called.
12.6.2/4
[...] if a member of X is neither specified in the
constructor's `mem-initializers´, nor default-initialized, nor
initialized during execution of the body of the constructor
[...]
Le premier extrait dit clairement que `this´ est utilisable dans
le *corps* d'une fonction membre non-statique, alors que le second
/semble/ faire une différence entre le corps d'un constructeur et
son `ctor-initializer´.
Je n'ai cependant pas réussi à trouver un passage clair sur
l'appartenance ou non du `ctor-initializer´ au corps de son
constructeur. S'il devait s'avérer qu'il n'y appartient pas, il ne
serait alors pas possible d'y utiliser `this´, non ?
Ce qui suggèrerait que l'utilisation de this dans la liste
d'initialisation serait illégale.
Tous les compilateurs le permettent, et je suis assez sûr que
c'était l'intention du comité de le permettra.
Par la suite, il y a la question de ce qu'on peut faire avec this à
ce moment. Dans la liste d'intialisation, this est un pointeur à un
objet non encore construit. Ça nous amène à §3.8/5, qui précise ce
qu'on peut faire avec un tel pointeur.
Une des choses qu'on peut faire, c'est le copier -- le passer en
tant que paramétre est donc authorisé, et garanti à fonctionner. En
revanche, si on le passe, on peut supposer que le constructeur
auquel on l'a passé va en faire quelque chose avec lui. Si tout ce
qu'il fait, c'est de le copier, pour l'utiliser plut tard (comme
c'est le cas ici), pas de problème. S'il fait quelque chose de plus,
ne serait-ce que de le convertir en un pointeur à une classe de
base, il y a un comportement indéfini. C'est d'ailleur le sens de
l'avertissement de VC++ : a priori, tu ne sais pas ce que fait la
classe avec le pointeur que tu lui passe. C'est donc une source
potentielle d'un comportement indéfini.
Dans ce cas-ci, l'idiome est assez courant. Assez pour que je crois
Microsoft a eu tort d'émettre un avertissment, même si ça part d'un
bon sentiment.
drkm <darkman_spam@yahoo.fr> wrote in message
news:<wkr850u2ip.fsf@yahoo.fr>...
En même temps, en cherchant un peu dans la norme, j'ai trouvé
ceci :
9.3.2/1
In the body of a nonstatic (9.3) member function, the keyword
`this´ is a non-lvalue expression whose value is the address
of the object for which the function is called.
12.6.2/4
[...] if a member of X is neither specified in the
constructor's `mem-initializers´, nor default-initialized, nor
initialized during execution of the body of the constructor
[...]
Le premier extrait dit clairement que `this´ est utilisable dans
le *corps* d'une fonction membre non-statique, alors que le second
/semble/ faire une différence entre le corps d'un constructeur et
son `ctor-initializer´.
Je n'ai cependant pas réussi à trouver un passage clair sur
l'appartenance ou non du `ctor-initializer´ au corps de son
constructeur. S'il devait s'avérer qu'il n'y appartient pas, il ne
serait alors pas possible d'y utiliser `this´, non ?
Ce qui suggèrerait que l'utilisation de this dans la liste
d'initialisation serait illégale.
Tous les compilateurs le permettent, et je suis assez sûr que
c'était l'intention du comité de le permettra.
Par la suite, il y a la question de ce qu'on peut faire avec this à
ce moment. Dans la liste d'intialisation, this est un pointeur à un
objet non encore construit. Ça nous amène à §3.8/5, qui précise ce
qu'on peut faire avec un tel pointeur.
Une des choses qu'on peut faire, c'est le copier -- le passer en
tant que paramétre est donc authorisé, et garanti à fonctionner. En
revanche, si on le passe, on peut supposer que le constructeur
auquel on l'a passé va en faire quelque chose avec lui. Si tout ce
qu'il fait, c'est de le copier, pour l'utiliser plut tard (comme
c'est le cas ici), pas de problème. S'il fait quelque chose de plus,
ne serait-ce que de le convertir en un pointeur à une classe de
base, il y a un comportement indéfini. C'est d'ailleur le sens de
l'avertissement de VC++ : a priori, tu ne sais pas ce que fait la
classe avec le pointeur que tu lui passe. C'est donc une source
potentielle d'un comportement indéfini.
Dans ce cas-ci, l'idiome est assez courant. Assez pour que je crois
Microsoft a eu tort d'émettre un avertissment, même si ça part d'un
bon sentiment.
drkm wrote in message
news:...En même temps, en cherchant un peu dans la norme, j'ai trouvé
ceci :
9.3.2/1
In the body of a nonstatic (9.3) member function, the keyword
`this´ is a non-lvalue expression whose value is the address
of the object for which the function is called.
12.6.2/4
[...] if a member of X is neither specified in the
constructor's `mem-initializers´, nor default-initialized, nor
initialized during execution of the body of the constructor
[...]
Le premier extrait dit clairement que `this´ est utilisable dans
le *corps* d'une fonction membre non-statique, alors que le second
/semble/ faire une différence entre le corps d'un constructeur et
son `ctor-initializer´.
Je n'ai cependant pas réussi à trouver un passage clair sur
l'appartenance ou non du `ctor-initializer´ au corps de son
constructeur. S'il devait s'avérer qu'il n'y appartient pas, il ne
serait alors pas possible d'y utiliser `this´, non ?
Ce qui suggèrerait que l'utilisation de this dans la liste
d'initialisation serait illégale.
Tous les compilateurs le permettent, et je suis assez sûr que
c'était l'intention du comité de le permettra.
Par la suite, il y a la question de ce qu'on peut faire avec this à
ce moment. Dans la liste d'intialisation, this est un pointeur à un
objet non encore construit. Ça nous amène à §3.8/5, qui précise ce
qu'on peut faire avec un tel pointeur.
Une des choses qu'on peut faire, c'est le copier -- le passer en
tant que paramétre est donc authorisé, et garanti à fonctionner. En
revanche, si on le passe, on peut supposer que le constructeur
auquel on l'a passé va en faire quelque chose avec lui. Si tout ce
qu'il fait, c'est de le copier, pour l'utiliser plut tard (comme
c'est le cas ici), pas de problème. S'il fait quelque chose de plus,
ne serait-ce que de le convertir en un pointeur à une classe de
base, il y a un comportement indéfini. C'est d'ailleur le sens de
l'avertissement de VC++ : a priori, tu ne sais pas ce que fait la
classe avec le pointeur que tu lui passe. C'est donc une source
potentielle d'un comportement indéfini.
Dans ce cas-ci, l'idiome est assez courant. Assez pour que je crois
Microsoft a eu tort d'émettre un avertissment, même si ça part d'un
bon sentiment.
writes:drkm wrote in message
news:...En même temps, en cherchant un peu dans la norme, j'ai trouvé
ceci :
9.3.2/1
In the body of a nonstatic (9.3) member function, the keyword
`this´ is a non-lvalue expression whose value is the address
of the object for which the function is called.
12.6.2/4
[...] if a member of X is neither specified in the
constructor's `mem-initializers´, nor default-initialized, nor
initialized during execution of the body of the constructor
[...]
Le premier extrait dit clairement que `this´ est utilisable dans
le *corps* d'une fonction membre non-statique, alors que le second
/semble/ faire une différence entre le corps d'un constructeur et
son `ctor-initializer´.
Je n'ai cependant pas réussi à trouver un passage clair sur
l'appartenance ou non du `ctor-initializer´ au corps de son
constructeur. S'il devait s'avérer qu'il n'y appartient pas, il ne
serait alors pas possible d'y utiliser `this´, non ?
Ce qui suggèrerait que l'utilisation de this dans la liste
d'initialisation serait illégale.
Oui. Si le `ctor-initializer´ ne fait pas partie du corps du
constructeur.
Tous les compilateurs le permettent, et je suis assez sûr que
c'était l'intention du comité de le permettra.
C'est ce que j'imagine. Mais ce ne serait pas, je pense, le premier
exemple de contradiction entre l'intention du comité et sa rédaction
dans la norme ...
D'autant que je ne vois pas de raison pour un compilateur de
connaître la valeur de `this´ dans le corps du constructeur (je veux
dire après l'accolade ouvrante) et non dans la liste d'initialistion.
Par la suite, il y a la question de ce qu'on peut faire avec this à
ce moment. Dans la liste d'intialisation, this est un pointeur à un
objet non encore construit. Ça nous amène à §3.8/5, qui précise ce
qu'on peut faire avec un tel pointeur.
Je comprend l'interdiction de conversion d'un pointeur vers un objet
de type non-POD, dans le cas d'opérateurs de conversion définis par
l'utilisateur. Mais je ne comprend pas la motivation derrière
l'interdiction de la conversion vers un type de classe de base. Comme
je l'ai dis dans mon dernier article, il me semble que la conversion
d'adresses d'objets dans la même hiérarchie ne requiérerait [*] pas
que les objets soient construits.
[*] Je parle du point de vue de ce que requérerait une
implémentation, non de ce que requière la norme.
Une des choses qu'on peut faire, c'est le copier -- le passer en
tant que paramétre est donc authorisé, et garanti à fonctionner. En
revanche, si on le passe, on peut supposer que le constructeur
auquel on l'a passé va en faire quelque chose avec lui. Si tout ce
qu'il fait, c'est de le copier, pour l'utiliser plut tard (comme
c'est le cas ici), pas de problème. S'il fait quelque chose de plus,
ne serait-ce que de le convertir en un pointeur à une classe de
base, il y a un comportement indéfini. C'est d'ailleur le sens de
l'avertissement de VC++ : a priori, tu ne sais pas ce que fait la
classe avec le pointeur que tu lui passe. C'est donc une source
potentielle d'un comportement indéfini.
Dans ce cas-ci, l'idiome est assez courant. Assez pour que je crois
Microsoft a eu tort d'émettre un avertissment, même si ça part d'un
bon sentiment.
Du moins, de l'émettre sans options particulières. Je le verrais
bien dans un mode « full warnings ». Un peu comme `-Weffc++´ peut
avec GCC nous submerger d'avertissements inutiles, ou en émettre de
très pertinents.
Mais j'aimerais savoir ce qu'il en est pour l'appartenance du
`ctor-initializer´ au corps du constructeur. Quelqu'un a-t-il une
piste ?
kanze@gabi-soft.fr writes:
drkm <darkman_spam@yahoo.fr> wrote in message
news:<wkr850u2ip.fsf@yahoo.fr>...
En même temps, en cherchant un peu dans la norme, j'ai trouvé
ceci :
9.3.2/1
In the body of a nonstatic (9.3) member function, the keyword
`this´ is a non-lvalue expression whose value is the address
of the object for which the function is called.
12.6.2/4
[...] if a member of X is neither specified in the
constructor's `mem-initializers´, nor default-initialized, nor
initialized during execution of the body of the constructor
[...]
Le premier extrait dit clairement que `this´ est utilisable dans
le *corps* d'une fonction membre non-statique, alors que le second
/semble/ faire une différence entre le corps d'un constructeur et
son `ctor-initializer´.
Je n'ai cependant pas réussi à trouver un passage clair sur
l'appartenance ou non du `ctor-initializer´ au corps de son
constructeur. S'il devait s'avérer qu'il n'y appartient pas, il ne
serait alors pas possible d'y utiliser `this´, non ?
Ce qui suggèrerait que l'utilisation de this dans la liste
d'initialisation serait illégale.
Oui. Si le `ctor-initializer´ ne fait pas partie du corps du
constructeur.
Tous les compilateurs le permettent, et je suis assez sûr que
c'était l'intention du comité de le permettra.
C'est ce que j'imagine. Mais ce ne serait pas, je pense, le premier
exemple de contradiction entre l'intention du comité et sa rédaction
dans la norme ...
D'autant que je ne vois pas de raison pour un compilateur de
connaître la valeur de `this´ dans le corps du constructeur (je veux
dire après l'accolade ouvrante) et non dans la liste d'initialistion.
Par la suite, il y a la question de ce qu'on peut faire avec this à
ce moment. Dans la liste d'intialisation, this est un pointeur à un
objet non encore construit. Ça nous amène à §3.8/5, qui précise ce
qu'on peut faire avec un tel pointeur.
Je comprend l'interdiction de conversion d'un pointeur vers un objet
de type non-POD, dans le cas d'opérateurs de conversion définis par
l'utilisateur. Mais je ne comprend pas la motivation derrière
l'interdiction de la conversion vers un type de classe de base. Comme
je l'ai dis dans mon dernier article, il me semble que la conversion
d'adresses d'objets dans la même hiérarchie ne requiérerait [*] pas
que les objets soient construits.
[*] Je parle du point de vue de ce que requérerait une
implémentation, non de ce que requière la norme.
Une des choses qu'on peut faire, c'est le copier -- le passer en
tant que paramétre est donc authorisé, et garanti à fonctionner. En
revanche, si on le passe, on peut supposer que le constructeur
auquel on l'a passé va en faire quelque chose avec lui. Si tout ce
qu'il fait, c'est de le copier, pour l'utiliser plut tard (comme
c'est le cas ici), pas de problème. S'il fait quelque chose de plus,
ne serait-ce que de le convertir en un pointeur à une classe de
base, il y a un comportement indéfini. C'est d'ailleur le sens de
l'avertissement de VC++ : a priori, tu ne sais pas ce que fait la
classe avec le pointeur que tu lui passe. C'est donc une source
potentielle d'un comportement indéfini.
Dans ce cas-ci, l'idiome est assez courant. Assez pour que je crois
Microsoft a eu tort d'émettre un avertissment, même si ça part d'un
bon sentiment.
Du moins, de l'émettre sans options particulières. Je le verrais
bien dans un mode « full warnings ». Un peu comme `-Weffc++´ peut
avec GCC nous submerger d'avertissements inutiles, ou en émettre de
très pertinents.
Mais j'aimerais savoir ce qu'il en est pour l'appartenance du
`ctor-initializer´ au corps du constructeur. Quelqu'un a-t-il une
piste ?
writes:drkm wrote in message
news:...En même temps, en cherchant un peu dans la norme, j'ai trouvé
ceci :
9.3.2/1
In the body of a nonstatic (9.3) member function, the keyword
`this´ is a non-lvalue expression whose value is the address
of the object for which the function is called.
12.6.2/4
[...] if a member of X is neither specified in the
constructor's `mem-initializers´, nor default-initialized, nor
initialized during execution of the body of the constructor
[...]
Le premier extrait dit clairement que `this´ est utilisable dans
le *corps* d'une fonction membre non-statique, alors que le second
/semble/ faire une différence entre le corps d'un constructeur et
son `ctor-initializer´.
Je n'ai cependant pas réussi à trouver un passage clair sur
l'appartenance ou non du `ctor-initializer´ au corps de son
constructeur. S'il devait s'avérer qu'il n'y appartient pas, il ne
serait alors pas possible d'y utiliser `this´, non ?
Ce qui suggèrerait que l'utilisation de this dans la liste
d'initialisation serait illégale.
Oui. Si le `ctor-initializer´ ne fait pas partie du corps du
constructeur.
Tous les compilateurs le permettent, et je suis assez sûr que
c'était l'intention du comité de le permettra.
C'est ce que j'imagine. Mais ce ne serait pas, je pense, le premier
exemple de contradiction entre l'intention du comité et sa rédaction
dans la norme ...
D'autant que je ne vois pas de raison pour un compilateur de
connaître la valeur de `this´ dans le corps du constructeur (je veux
dire après l'accolade ouvrante) et non dans la liste d'initialistion.
Par la suite, il y a la question de ce qu'on peut faire avec this à
ce moment. Dans la liste d'intialisation, this est un pointeur à un
objet non encore construit. Ça nous amène à §3.8/5, qui précise ce
qu'on peut faire avec un tel pointeur.
Je comprend l'interdiction de conversion d'un pointeur vers un objet
de type non-POD, dans le cas d'opérateurs de conversion définis par
l'utilisateur. Mais je ne comprend pas la motivation derrière
l'interdiction de la conversion vers un type de classe de base. Comme
je l'ai dis dans mon dernier article, il me semble que la conversion
d'adresses d'objets dans la même hiérarchie ne requiérerait [*] pas
que les objets soient construits.
[*] Je parle du point de vue de ce que requérerait une
implémentation, non de ce que requière la norme.
Une des choses qu'on peut faire, c'est le copier -- le passer en
tant que paramétre est donc authorisé, et garanti à fonctionner. En
revanche, si on le passe, on peut supposer que le constructeur
auquel on l'a passé va en faire quelque chose avec lui. Si tout ce
qu'il fait, c'est de le copier, pour l'utiliser plut tard (comme
c'est le cas ici), pas de problème. S'il fait quelque chose de plus,
ne serait-ce que de le convertir en un pointeur à une classe de
base, il y a un comportement indéfini. C'est d'ailleur le sens de
l'avertissement de VC++ : a priori, tu ne sais pas ce que fait la
classe avec le pointeur que tu lui passe. C'est donc une source
potentielle d'un comportement indéfini.
Dans ce cas-ci, l'idiome est assez courant. Assez pour que je crois
Microsoft a eu tort d'émettre un avertissment, même si ça part d'un
bon sentiment.
Du moins, de l'émettre sans options particulières. Je le verrais
bien dans un mode « full warnings ». Un peu comme `-Weffc++´ peut
avec GCC nous submerger d'avertissements inutiles, ou en émettre de
très pertinents.
Mais j'aimerais savoir ce qu'il en est pour l'appartenance du
`ctor-initializer´ au corps du constructeur. Quelqu'un a-t-il une
piste ?
writes:drkm wrote in message
news:...J'ajouterais que le code suivant compile parfaitement sous GCC,
sans diagnostique :
Et pourtant, ce n'est pas légal:-).cat fclc++.cc
#include <iostream>
Tu as oublié l'« #include <ostream> ». Les opérateurs << ne sont pas
définis.
Yep. Je ne prend jamais la « peine » de l'inclure dans des petits
tests rapides, et bien sûr, ne pense pas à l'ajouter si je poste le
code :-(.
class B
{
public:
B( class A* pA ) : m_pA( pA ) { }
class A* m_pA ;
} ;
class A
{
public:
A() : m_B( this ) { }
const B m_B ;
} ;
Ajoutons un:
class C : public A
{
public:
C() : unDeuxiemeB( this ) {}
B const unDeuxiemeB ;
} ;
G++ ne dit toujours rien. Et pourtant, c'est illégal. La conversion
de this (un C*) en A* a un comportement indéfini.
Yep.En fait, il y a de fortes chances que ça marche, tant qu'il n'y a
pas d'héritage virtuel. Mais la norme l'interdit explicitement.
Je ne vois pas exactement comment l'héritage virtuel complique
l'affaire. Lors d'une conversion entre deux types d'une même
hiérarchie avec héritage virtuel, il est possible que le compilateur
doive ajouter ou retrancher un petit décalage à la valeur du pointeur.
Et si je comprend bien, la valeur de ce décalage est connue dès que
les types sont connus (ce qui est le cas dans une conversion).
Si l'on a l'adresse d'un objet, on peux calculer celle d'un
sous-objet ou sur-objet, indépendamment que ces objets soient ou non
construits (les adresses sont donc plutôt celles d'endroits où se
*trouveraient* les objets).
kanze@gabi-soft.fr writes:
drkm <darkman_spam@yahoo.fr> wrote in message
news:<wkisqcu0mm.fsf@yahoo.fr>...
J'ajouterais que le code suivant compile parfaitement sous GCC,
sans diagnostique :
Et pourtant, ce n'est pas légal:-).
cat fclc++.cc
#include <iostream>
Tu as oublié l'« #include <ostream> ». Les opérateurs << ne sont pas
définis.
Yep. Je ne prend jamais la « peine » de l'inclure dans des petits
tests rapides, et bien sûr, ne pense pas à l'ajouter si je poste le
code :-(.
class B
{
public:
B( class A* pA ) : m_pA( pA ) { }
class A* m_pA ;
} ;
class A
{
public:
A() : m_B( this ) { }
const B m_B ;
} ;
Ajoutons un:
class C : public A
{
public:
C() : unDeuxiemeB( this ) {}
B const unDeuxiemeB ;
} ;
G++ ne dit toujours rien. Et pourtant, c'est illégal. La conversion
de this (un C*) en A* a un comportement indéfini.
Yep.
En fait, il y a de fortes chances que ça marche, tant qu'il n'y a
pas d'héritage virtuel. Mais la norme l'interdit explicitement.
Je ne vois pas exactement comment l'héritage virtuel complique
l'affaire. Lors d'une conversion entre deux types d'une même
hiérarchie avec héritage virtuel, il est possible que le compilateur
doive ajouter ou retrancher un petit décalage à la valeur du pointeur.
Et si je comprend bien, la valeur de ce décalage est connue dès que
les types sont connus (ce qui est le cas dans une conversion).
Si l'on a l'adresse d'un objet, on peux calculer celle d'un
sous-objet ou sur-objet, indépendamment que ces objets soient ou non
construits (les adresses sont donc plutôt celles d'endroits où se
*trouveraient* les objets).
writes:drkm wrote in message
news:...J'ajouterais que le code suivant compile parfaitement sous GCC,
sans diagnostique :
Et pourtant, ce n'est pas légal:-).cat fclc++.cc
#include <iostream>
Tu as oublié l'« #include <ostream> ». Les opérateurs << ne sont pas
définis.
Yep. Je ne prend jamais la « peine » de l'inclure dans des petits
tests rapides, et bien sûr, ne pense pas à l'ajouter si je poste le
code :-(.
class B
{
public:
B( class A* pA ) : m_pA( pA ) { }
class A* m_pA ;
} ;
class A
{
public:
A() : m_B( this ) { }
const B m_B ;
} ;
Ajoutons un:
class C : public A
{
public:
C() : unDeuxiemeB( this ) {}
B const unDeuxiemeB ;
} ;
G++ ne dit toujours rien. Et pourtant, c'est illégal. La conversion
de this (un C*) en A* a un comportement indéfini.
Yep.En fait, il y a de fortes chances que ça marche, tant qu'il n'y a
pas d'héritage virtuel. Mais la norme l'interdit explicitement.
Je ne vois pas exactement comment l'héritage virtuel complique
l'affaire. Lors d'une conversion entre deux types d'une même
hiérarchie avec héritage virtuel, il est possible que le compilateur
doive ajouter ou retrancher un petit décalage à la valeur du pointeur.
Et si je comprend bien, la valeur de ce décalage est connue dès que
les types sont connus (ce qui est le cas dans une conversion).
Si l'on a l'adresse d'un objet, on peux calculer celle d'un
sous-objet ou sur-objet, indépendamment que ces objets soient ou non
construits (les adresses sont donc plutôt celles d'endroits où se
*trouveraient* les objets).
C'est seulement pour dire que le fait qu'il compile n'en prouve pas
la légalité.
Je ne vois pas exactement comment l'héritage virtuel complique
l'affaire.
Le problème avec l'héritage virtuel, c'est que ce décalage dépend du
type le plus dérivé, à construire.
C'est seulement pour dire que le fait qu'il compile n'en prouve pas
la légalité.
Je ne vois pas exactement comment l'héritage virtuel complique
l'affaire.
Le problème avec l'héritage virtuel, c'est que ce décalage dépend du
type le plus dérivé, à construire.
C'est seulement pour dire que le fait qu'il compile n'en prouve pas
la légalité.
Je ne vois pas exactement comment l'héritage virtuel complique
l'affaire.
Le problème avec l'héritage virtuel, c'est que ce décalage dépend du
type le plus dérivé, à construire.