je suis en train de développer une bibliothèque C++, et je rencontre des
problèmes à l'exécution avec certains couples machines-compilateurs
(plantages de toute la batterie de tests unitaires sur différents objets
STL) qui me font douter de certains usages C++ concernant la définition
de chaînes constantes (même si pourtant cela a l'air simple, ou devrait
l'être !).
Dans un fichier CeylanUniformResourceIdentifier.h je déclare :
J'ai un doute car ProtocolSeparator est un objet qui serait à construire
avant la première instruction de main (licite ? dangereux ?), et
valgrind me sort :
"""
==30157== Invalid write of size 4
==30157== at 0x40D3165: _GLOBAL__I__ZN6Ceylan3URI17ProtocolSeparatorE
(CeylanTypes.h:432)
==30157== by 0x40D3324: (within
/home/sye/tmp-Ceylan-test-install/lib/libCeylan-0.3.so.0.0.3)
==30157== by 0x40524C8: (within
/home/sye/tmp-Ceylan-test-install/lib/libCeylan-0.3.so.0.0.3)
==30157== by 0x400B70C: call_init (in /lib/ld-2.3.6.so)
==30157== by 0x400B7F1: _dl_init (in /lib/ld-2.3.6.so)
==30157== by 0x400081E: (within /lib/ld-2.3.6.so)
==30157== Address 0xBEFFCBD8 is not stack'd, malloc'd or (recently) free'd
"""
_GLOBAL__I__ZN6Ceylan3URI17ProtocolSeparatorE décrypté donne : "global
constructors keyed to Ceylan::URI::ProtocolSeparator". Mon doute est
accentué par le fait que la référence mentionnée (CeylanTypes.h:432) n'a
strictement aucun rapport avec ProtocolSeparator et pointe sur :
"""
typedef std::list<Ceylan::Uint16>::size_type ListSize ;
"""
(c'est un raccourci d'écriture [et peut-être aussi une mauvaise
pratique] pour fournir au développeur un type plus simple à manier).
Je sais qu'il serait possible d'encapsuler chacune de ces chaînes
constantes par une fonction spécifique qui la retourne (ex :
) mais je me passerais bien d'une telle encapsulation si elle est
facultative.
Vous serait-il possible de m'indiquer si d'emblée, purement sur le plan
du langage C++, ces formes sont correctes ? (après je sens que je vais
être bon pour continuer sur les listes de gcc et de valgrind)
| Merci à Fabien et à toi pour vos réponses. | | Si je n'utilise pas cette variable "ProtocolSeparator" en argument d'une | autre construction de type classe-statique ou extern, i.e. si, a priori, | sa première utilisation est à l'intérieur de main(), alors (je m'étais | dit que) on est assuré que toutes les constructions situées en dehors de | toute fonction seraient achevées à l'entrée dans main().
Si tu n'utilises pas cette variable avant d'entrer dans main(), normalement le système devrait procéder à son initialisation effective, avant sa première utilisation une fois le control d'exécution entré dans main -- quelque part dedans.
T'est-il possible de réduire le programme à quelque chose d'assez minimal qui permette de reproduire le problème ? J'ai perdu ma boule de cristal à l'aéroport alors je ne peux pas beaucoup t'aider juste par voyance.
| Merci à Fabien et à toi pour vos réponses.
|
| Si je n'utilise pas cette variable "ProtocolSeparator" en argument d'une
| autre construction de type classe-statique ou extern, i.e. si, a priori,
| sa première utilisation est à l'intérieur de main(), alors (je m'étais
| dit que) on est assuré que toutes les constructions situées en dehors de
| toute fonction seraient achevées à l'entrée dans main().
Si tu n'utilises pas cette variable avant d'entrer dans main(),
normalement le système devrait procéder à son initialisation
effective, avant sa première utilisation une fois le control
d'exécution entré dans main -- quelque part dedans.
T'est-il possible de réduire le programme à quelque chose d'assez
minimal qui permette de reproduire le problème ? J'ai perdu ma boule de
cristal à l'aéroport alors je ne peux pas beaucoup t'aider juste par
voyance.
| Merci à Fabien et à toi pour vos réponses. | | Si je n'utilise pas cette variable "ProtocolSeparator" en argument d'une | autre construction de type classe-statique ou extern, i.e. si, a priori, | sa première utilisation est à l'intérieur de main(), alors (je m'étais | dit que) on est assuré que toutes les constructions situées en dehors de | toute fonction seraient achevées à l'entrée dans main().
Si tu n'utilises pas cette variable avant d'entrer dans main(), normalement le système devrait procéder à son initialisation effective, avant sa première utilisation une fois le control d'exécution entré dans main -- quelque part dedans.
T'est-il possible de réduire le programme à quelque chose d'assez minimal qui permette de reproduire le problème ? J'ai perdu ma boule de cristal à l'aéroport alors je ne peux pas beaucoup t'aider juste par voyance.
-- Gaby
Gabriel Dos Reis
Sylvain writes:
[...]
| c'est le cas individuel (chaque object static est construit à l'entrée | de main) mais il n'y a pas de règle d'ensemble: chacun de ces objects | statiques est contruit dans un ordre imprévisible.
Pas exactement. L'ordre, dans une unité de traduction donnée, est spéifié.
-- Gaby
Sylvain <noSpam@mail.net> writes:
[...]
| c'est le cas individuel (chaque object static est construit à l'entrée
| de main) mais il n'y a pas de règle d'ensemble: chacun de ces objects
| statiques est contruit dans un ordre imprévisible.
Pas exactement. L'ordre, dans une unité de traduction donnée, est spéifié.
| c'est le cas individuel (chaque object static est construit à l'entrée | de main) mais il n'y a pas de règle d'ensemble: chacun de ces objects | statiques est contruit dans un ordre imprévisible.
Pas exactement. L'ordre, dans une unité de traduction donnée, est spéifié.
-- Gaby
Fabien LE LEZ
On 24 Jun 2006 21:48:06 +0200, Jean-Marc Bourguet :
static std::string const ma_chaine ("://");
const implique static si il n'y a pas une déclaration antérieure qui indique que c'est avec un "linkage" externe.
Même si le "static" est de toutes façons implicite, ne devrait-on pas le mettre explicitement ?
De même, dans le code
struct A { virtual void f(); } struct B { (virtual) void f(); }
le "virtual" est implicite ; doit-on tout de même l'écrire explicitement ?
On 24 Jun 2006 21:48:06 +0200, Jean-Marc Bourguet <jm@bourguet.org>:
static std::string const ma_chaine ("://");
const implique static si il n'y a pas une déclaration
antérieure qui indique que c'est avec un "linkage" externe.
Même si le "static" est de toutes façons implicite, ne devrait-on pas
le mettre explicitement ?
De même, dans le code
struct A { virtual void f(); }
struct B { (virtual) void f(); }
le "virtual" est implicite ; doit-on tout de même l'écrire
explicitement ?
On 24 Jun 2006 21:48:06 +0200, Jean-Marc Bourguet :
static std::string const ma_chaine ("://");
const implique static si il n'y a pas une déclaration antérieure qui indique que c'est avec un "linkage" externe.
Même si le "static" est de toutes façons implicite, ne devrait-on pas le mettre explicitement ?
De même, dans le code
struct A { virtual void f(); } struct B { (virtual) void f(); }
le "virtual" est implicite ; doit-on tout de même l'écrire explicitement ?
Sylvain
Fabien LE LEZ wrote on 25/06/2006 02:37:
De même, dans le code
struct A { virtual void f(); } struct B { (virtual) void f(); }
le "virtual" est implicite ; doit-on tout de même l'écrire explicitement ?
écrit comme cela B::f n'est pas virtuel du tout (ni implicitement, ni clairement explicitement) -- une struct C héritant de B et récouvrant f() aura accès à B::f(), un A* contenant un B& appelera A::f
tu voulais surement écrire:
struct A { virtual void f(); } struct B : A { [virtual] void f(); }
dans ce cas, en effet B::f est implicitement virtuel est la présence ou non du mot clé 'virtual' est affaire de gout; il est de bonne pratique de le mettre si, basiquement, cela apporte une information immédiate (accès à B.h plutot que A.h si header distincts par exemple).
Sylvain.
Fabien LE LEZ wrote on 25/06/2006 02:37:
De même, dans le code
struct A { virtual void f(); }
struct B { (virtual) void f(); }
le "virtual" est implicite ; doit-on tout de même l'écrire
explicitement ?
écrit comme cela B::f n'est pas virtuel du tout (ni implicitement, ni
clairement explicitement) -- une struct C héritant de B et récouvrant
f() aura accès à B::f(), un A* contenant un B& appelera A::f
tu voulais surement écrire:
struct A { virtual void f(); }
struct B : A { [virtual] void f(); }
dans ce cas, en effet B::f est implicitement virtuel est la présence ou
non du mot clé 'virtual' est affaire de gout; il est de bonne pratique
de le mettre si, basiquement, cela apporte une information immédiate
(accès à B.h plutot que A.h si header distincts par exemple).
struct A { virtual void f(); } struct B { (virtual) void f(); }
le "virtual" est implicite ; doit-on tout de même l'écrire explicitement ?
écrit comme cela B::f n'est pas virtuel du tout (ni implicitement, ni clairement explicitement) -- une struct C héritant de B et récouvrant f() aura accès à B::f(), un A* contenant un B& appelera A::f
tu voulais surement écrire:
struct A { virtual void f(); } struct B : A { [virtual] void f(); }
dans ce cas, en effet B::f est implicitement virtuel est la présence ou non du mot clé 'virtual' est affaire de gout; il est de bonne pratique de le mettre si, basiquement, cela apporte une information immédiate (accès à B.h plutot que A.h si header distincts par exemple).
Sylvain.
Sylvain
Sylvain se mélangea les touches on 25/06/2006 02:47:
écrit comme cela B::f
en comprenant que tu faisais référence à la forme sans 'virtual'...
un A* contenant un B& appelera A::f
un C* contenant un B&, appelera B::f
Sylvain.
Sylvain se mélangea les touches on 25/06/2006 02:47:
écrit comme cela B::f
en comprenant que tu faisais référence à la forme sans 'virtual'...
Sylvain se mélangea 2 fois les touches on 25/06/2006 02:47:
écrit comme cela B::f
en comprenant que tu faisais référence à la forme sans 'virtual'...
un A* contenant un B& appelera A::f
un B* contenant un C& appelera B::f
Sylvain.
Sylvain
Fabien LE LEZ wrote on 25/06/2006 02:37:
On 24 Jun 2006 21:48:06 +0200, Jean-Marc Bourguet :
static std::string const ma_chaine ("://"); const implique static si il n'y a pas une déclaration
antérieure qui indique que c'est avec un "linkage" externe.
Même si le "static" est de toutes façons implicite, ne devrait-on pas le mettre explicitement ?
De même, dans le code
struct A { virtual void f(); } struct B { (virtual) void f(); }
le "virtual" est implicite ; doit-on tout de même l'écrire explicitement ?
oups, peut être était-ce vraiment l'écriture intentionelle, se traduisant par "si je n'indique pas 'virtual' ai-je tout de même les attributs d'une déclaration (explicitement) virtuelle" ?
je ne vais pas me contenter d'un 'non' car cela a évidemment un impact sur le design des classes et qu'il est utile d'avoir en tête ces conséquences; si ce n'est pas ta question, cela servira peut être à d'autres...
petit détour: en Java, une méthode d'instance est implicitement virtuelle. ceci implique que: - une résolution virtuelle est tjrs effectuée lors de l'appel d'une méthode d'instance, - un client ne peut bypasser la hiérarchie fournie par l'instance (quand il invoque la méthode f() de l'instance c'est la méthode surchargée qui est appelée.
à contrario en C++, la virtualité n'est pas implicite et doit être déclarée par la classe qui introduit une méthode et souhaite la rendre virtuelle, notons pour ne pas y revenir qu'il n'est pas possible de rendre virtuele une méthode surchargée d'une classe parent qui n'était pas originellmeent virtuelle.
cette non virtualité systématique implique que par défaut la surcharge ne masque pas une méthode - le client d'une instance ayant surchargé des méthodes de ses parents a accès aux méthodes de la classe comme à celles du (ou des) parents (on omets ici les restriction de visibilité explicite par protected et private, l'instance est considérée comme une structure publique pour simplifier)
ainsi si:
struct A { void f(){} }; struct B : A { void f(){} };
alors ayant:
A a; B b;
a.f(); // est valide, bien sur et également b.f(); // qui invoque B::f() avec le contexte de b, comme (A& b).f(); // qui appelle A::f() avec le contexte de b
de plus la résolution n'étant pas "dynamisé" par une déclaration virtuelle; un pointeur A* même initialisé avec une instance de B ne verra que les méthodes de A:
A* pa = &B; pa->f(); // invoque A::f() et non B::f().
(on vent arrêter là les détails verbieux)
si par contre nous déclarons la méthode virtuelle:
struct A { virtual void f(){} }; struct B : A { void f(){} };
alors la surcharge est maintenant masquante pour les clients de la classe:
b.f(); // invoque B::f() (A& b).f(); // invoque également B::f()
bien B a accès aux détails de A, on peut avoir:
void B::f(){ A::f(); } // appel à la 'super-méthode'
autre impact, la résolution d'appel est dynamique donc:
A* pa = &B; pa->f(); // invoque encore B::f().
la 1ière remarque (masquage) peut être vue comme une conséquence de ce second point, ou on peut voir ce second point comme le moyen d'apporter le premier (qui serait alors le but .. de l'encapsulation), le résultat est le même (la motivation et ses arcanes sont très différentes).
voila.
Sylvain.
Fabien LE LEZ wrote on 25/06/2006 02:37:
On 24 Jun 2006 21:48:06 +0200, Jean-Marc Bourguet <jm@bourguet.org>:
static std::string const ma_chaine ("://");
const implique static si il n'y a pas une déclaration
antérieure qui indique que c'est avec un "linkage" externe.
Même si le "static" est de toutes façons implicite, ne devrait-on pas
le mettre explicitement ?
De même, dans le code
struct A { virtual void f(); }
struct B { (virtual) void f(); }
le "virtual" est implicite ; doit-on tout de même l'écrire
explicitement ?
oups, peut être était-ce vraiment l'écriture intentionelle, se
traduisant par "si je n'indique pas 'virtual' ai-je tout de même les
attributs d'une déclaration (explicitement) virtuelle" ?
je ne vais pas me contenter d'un 'non' car cela a évidemment un impact
sur le design des classes et qu'il est utile d'avoir en tête ces
conséquences; si ce n'est pas ta question, cela servira peut être à
d'autres...
petit détour: en Java, une méthode d'instance est implicitement
virtuelle. ceci implique que:
- une résolution virtuelle est tjrs effectuée lors de l'appel d'une
méthode d'instance,
- un client ne peut bypasser la hiérarchie fournie par l'instance (quand
il invoque la méthode f() de l'instance c'est la méthode surchargée qui
est appelée.
à contrario en C++, la virtualité n'est pas implicite et doit être
déclarée par la classe qui introduit une méthode et souhaite la rendre
virtuelle, notons pour ne pas y revenir qu'il n'est pas possible de
rendre virtuele une méthode surchargée d'une classe parent qui n'était
pas originellmeent virtuelle.
cette non virtualité systématique implique que par défaut la surcharge
ne masque pas une méthode - le client d'une instance ayant surchargé des
méthodes de ses parents a accès aux méthodes de la classe comme à celles
du (ou des) parents (on omets ici les restriction de visibilité
explicite par protected et private, l'instance est considérée comme une
structure publique pour simplifier)
ainsi si:
struct A { void f(){} };
struct B : A { void f(){} };
alors ayant:
A a; B b;
a.f(); // est valide, bien sur et également
b.f(); // qui invoque B::f() avec le contexte de b, comme
(A& b).f(); // qui appelle A::f() avec le contexte de b
de plus la résolution n'étant pas "dynamisé" par une déclaration
virtuelle; un pointeur A* même initialisé avec une instance de B ne
verra que les méthodes de A:
A* pa = &B;
pa->f(); // invoque A::f() et non B::f().
(on vent arrêter là les détails verbieux)
si par contre nous déclarons la méthode virtuelle:
struct A { virtual void f(){} };
struct B : A { void f(){} };
alors la surcharge est maintenant masquante pour les clients de la classe:
b.f(); // invoque B::f()
(A& b).f(); // invoque également B::f()
bien B a accès aux détails de A, on peut avoir:
void B::f(){ A::f(); } // appel à la 'super-méthode'
autre impact, la résolution d'appel est dynamique donc:
A* pa = &B;
pa->f(); // invoque encore B::f().
la 1ière remarque (masquage) peut être vue comme une conséquence de ce
second point, ou on peut voir ce second point comme le moyen d'apporter
le premier (qui serait alors le but .. de l'encapsulation), le résultat
est le même (la motivation et ses arcanes sont très différentes).
On 24 Jun 2006 21:48:06 +0200, Jean-Marc Bourguet :
static std::string const ma_chaine ("://"); const implique static si il n'y a pas une déclaration
antérieure qui indique que c'est avec un "linkage" externe.
Même si le "static" est de toutes façons implicite, ne devrait-on pas le mettre explicitement ?
De même, dans le code
struct A { virtual void f(); } struct B { (virtual) void f(); }
le "virtual" est implicite ; doit-on tout de même l'écrire explicitement ?
oups, peut être était-ce vraiment l'écriture intentionelle, se traduisant par "si je n'indique pas 'virtual' ai-je tout de même les attributs d'une déclaration (explicitement) virtuelle" ?
je ne vais pas me contenter d'un 'non' car cela a évidemment un impact sur le design des classes et qu'il est utile d'avoir en tête ces conséquences; si ce n'est pas ta question, cela servira peut être à d'autres...
petit détour: en Java, une méthode d'instance est implicitement virtuelle. ceci implique que: - une résolution virtuelle est tjrs effectuée lors de l'appel d'une méthode d'instance, - un client ne peut bypasser la hiérarchie fournie par l'instance (quand il invoque la méthode f() de l'instance c'est la méthode surchargée qui est appelée.
à contrario en C++, la virtualité n'est pas implicite et doit être déclarée par la classe qui introduit une méthode et souhaite la rendre virtuelle, notons pour ne pas y revenir qu'il n'est pas possible de rendre virtuele une méthode surchargée d'une classe parent qui n'était pas originellmeent virtuelle.
cette non virtualité systématique implique que par défaut la surcharge ne masque pas une méthode - le client d'une instance ayant surchargé des méthodes de ses parents a accès aux méthodes de la classe comme à celles du (ou des) parents (on omets ici les restriction de visibilité explicite par protected et private, l'instance est considérée comme une structure publique pour simplifier)
ainsi si:
struct A { void f(){} }; struct B : A { void f(){} };
alors ayant:
A a; B b;
a.f(); // est valide, bien sur et également b.f(); // qui invoque B::f() avec le contexte de b, comme (A& b).f(); // qui appelle A::f() avec le contexte de b
de plus la résolution n'étant pas "dynamisé" par une déclaration virtuelle; un pointeur A* même initialisé avec une instance de B ne verra que les méthodes de A:
A* pa = &B; pa->f(); // invoque A::f() et non B::f().
(on vent arrêter là les détails verbieux)
si par contre nous déclarons la méthode virtuelle:
struct A { virtual void f(){} }; struct B : A { void f(){} };
alors la surcharge est maintenant masquante pour les clients de la classe:
b.f(); // invoque B::f() (A& b).f(); // invoque également B::f()
bien B a accès aux détails de A, on peut avoir:
void B::f(){ A::f(); } // appel à la 'super-méthode'
autre impact, la résolution d'appel est dynamique donc:
A* pa = &B; pa->f(); // invoque encore B::f().
la 1ière remarque (masquage) peut être vue comme une conséquence de ce second point, ou on peut voir ce second point comme le moyen d'apporter le premier (qui serait alors le but .. de l'encapsulation), le résultat est le même (la motivation et ses arcanes sont très différentes).
voila.
Sylvain.
Jean-Marc Bourguet
Olivier Boudeville writes:
Merci à tous pour vos réponses,
je déduis de tout cela que les trois formes :
- 'const std::string s = "foo";' dans le header - 'extern const std::string s ;' dans le header + "const std::string s = "foo" ;' dans l'implémentation - 'const std::string & get_s() ;' + sa définition
sont correctes, et que la troisième est probablement à privilégier en général.
La première doit fonctionner sauf si on s'attend à ce que &s fait dans des entêtes différents ait le même résultat (et à condition qu'on accepte la duplication).
La deuxième doit fonctionner sauf si on utilise la variable pour l'initialisation d'autres variables statiques dans d'autres unités de compilation.
Les trois méthodes ont un problème si la variable est utilisée durant la destruction d'autres variables statiques qui auront été construite avant elle.
A+
-- Jean-Marc FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html Site de usenet-fr: http://www.usenet-fr.news.eu.org
- 'const std::string s = "foo";' dans le header
- 'extern const std::string s ;' dans le header + "const std::string s
= "foo" ;' dans l'implémentation
- 'const std::string & get_s() ;' + sa définition
sont correctes, et que la troisième est probablement à privilégier en
général.
La première doit fonctionner sauf si on s'attend à ce que &s
fait dans des entêtes différents ait le même résultat (et à
condition qu'on accepte la duplication).
La deuxième doit fonctionner sauf si on utilise la variable
pour l'initialisation d'autres variables statiques dans
d'autres unités de compilation.
Les trois méthodes ont un problème si la variable est
utilisée durant la destruction d'autres variables statiques
qui auront été construite avant elle.
A+
--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
- 'const std::string s = "foo";' dans le header - 'extern const std::string s ;' dans le header + "const std::string s = "foo" ;' dans l'implémentation - 'const std::string & get_s() ;' + sa définition
sont correctes, et que la troisième est probablement à privilégier en général.
La première doit fonctionner sauf si on s'attend à ce que &s fait dans des entêtes différents ait le même résultat (et à condition qu'on accepte la duplication).
La deuxième doit fonctionner sauf si on utilise la variable pour l'initialisation d'autres variables statiques dans d'autres unités de compilation.
Les trois méthodes ont un problème si la variable est utilisée durant la destruction d'autres variables statiques qui auront été construite avant elle.
A+
-- Jean-Marc FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html Site de usenet-fr: http://www.usenet-fr.news.eu.org
Jean-Marc Bourguet
Fabien LE LEZ writes:
On 24 Jun 2006 21:48:06 +0200, Jean-Marc Bourguet :
static std::string const ma_chaine ("://");
const implique static si il n'y a pas une déclaration antérieure qui indique que c'est avec un "linkage" externe.
Même si le "static" est de toutes façons implicite, ne devrait-on pas le mettre explicitement ?
C'est une question de style à mon avis, pas de bonne pratique. Je voulais surtout faire remarquer que le cas n'était en rien différent de ce qui avait déjà été suggéré.
De même, dans le code
struct A { virtual void f(); } struct B { (virtual) void f(); }
le "virtual" est implicite ; doit-on tout de même l'écrire explicitement ?
A nouveau, pour moi c'est une affaire de style.
A+
-- Jean-Marc FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html Site de usenet-fr: http://www.usenet-fr.news.eu.org
Fabien LE LEZ <gramster@gramster.com> writes:
On 24 Jun 2006 21:48:06 +0200, Jean-Marc Bourguet <jm@bourguet.org>:
static std::string const ma_chaine ("://");
const implique static si il n'y a pas une déclaration
antérieure qui indique que c'est avec un "linkage" externe.
Même si le "static" est de toutes façons implicite, ne
devrait-on pas le mettre explicitement ?
C'est une question de style à mon avis, pas de bonne
pratique. Je voulais surtout faire remarquer que le cas
n'était en rien différent de ce qui avait déjà été suggéré.
De même, dans le code
struct A { virtual void f(); }
struct B { (virtual) void f(); }
le "virtual" est implicite ; doit-on tout de même l'écrire
explicitement ?
A nouveau, pour moi c'est une affaire de style.
A+
--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
On 24 Jun 2006 21:48:06 +0200, Jean-Marc Bourguet :
static std::string const ma_chaine ("://");
const implique static si il n'y a pas une déclaration antérieure qui indique que c'est avec un "linkage" externe.
Même si le "static" est de toutes façons implicite, ne devrait-on pas le mettre explicitement ?
C'est une question de style à mon avis, pas de bonne pratique. Je voulais surtout faire remarquer que le cas n'était en rien différent de ce qui avait déjà été suggéré.
De même, dans le code
struct A { virtual void f(); } struct B { (virtual) void f(); }
le "virtual" est implicite ; doit-on tout de même l'écrire explicitement ?
A nouveau, pour moi c'est une affaire de style.
A+
-- Jean-Marc FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html Site de usenet-fr: http://www.usenet-fr.news.eu.org
Falk Tannhäuser
Olivier Boudeville wrote:
Merci à tous pour vos réponses,
je déduis de tout cela que les trois formes :
- 'const std::string s = "foo";' dans le header - 'extern const std::string s ;' dans le header + "const std::string s = "foo" ;' dans l'implémentation - 'const std::string & get_s() ;' + sa définition
La quatrième forme 'extern char const s[];' dans le header + 'char const s[] = "foo";' dans l'implémentation ne présente pas le problème d'ordre d'initialisation des objets globaux qui se trouvent dans des unités de compilation différentes (cf. § 3.6.2/1) et nécessite pas l'introduction d'une fonction.
Falk
Olivier Boudeville wrote:
Merci à tous pour vos réponses,
je déduis de tout cela que les trois formes :
- 'const std::string s = "foo";' dans le header
- 'extern const std::string s ;' dans le header + "const std::string s
= "foo" ;' dans l'implémentation
- 'const std::string & get_s() ;' + sa définition
La quatrième forme
'extern char const s[];' dans le header +
'char const s[] = "foo";' dans l'implémentation ne présente pas
le problème d'ordre d'initialisation des objets globaux qui se
trouvent dans des unités de compilation différentes (cf. § 3.6.2/1)
et nécessite pas l'introduction d'une fonction.
- 'const std::string s = "foo";' dans le header - 'extern const std::string s ;' dans le header + "const std::string s = "foo" ;' dans l'implémentation - 'const std::string & get_s() ;' + sa définition
La quatrième forme 'extern char const s[];' dans le header + 'char const s[] = "foo";' dans l'implémentation ne présente pas le problème d'ordre d'initialisation des objets globaux qui se trouvent dans des unités de compilation différentes (cf. § 3.6.2/1) et nécessite pas l'introduction d'une fonction.