Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

initialisation des variables membres par défaut

73 réponses
Avatar
Richard Delorme
// ---------8<----------------------------
#include <iostream>

class A {
private:
int x;

public:
A() {};
~A() {};
void print() {
std::cout << x << std::endl;
}
};


int main() {
A t;
int y;


t.print();
std::cout << y << std::endl;

return 0;
}
// ---------8<----------------------------

Dans l'exemple ci-dessus, ni x, membre de la classe A, ni la variable
locale y ne sont initialisées.
gcc détecte le cas de la variable locale :
attention : ‘y’ may be used uninitialized in this function
mais reste silencieux sur la variable membre.
Valgrind signale les deux cas (de manière guère compréhensible d'ailleurs).

Personnellement je pensais comme Valgrind que la variable x devait être
initialisé explicitement dans le constructeur, par exemple en écrivant :
A() : x() {};
à la place du constructeur ci-dessus.

Néanmoins la lecture de blogs sur internet me laisse dans le doute. Par
exemple ici :
http://discuss.joelonsoftware.com/default.asp?joel.3.489111.50

On lit tout et son contraire. Qu'en est il en pratique ? (et en théorie
aussi d'ailleurs).

--
Richard

3 réponses

4 5 6 7 8
Avatar
Wykaaa
James Kanze a écrit :
On Jan 28, 9:34 pm, Wykaaa wrote:



[snip]


C'est juste une question de documentation d'interface.



En somme, tu es d'accord avec moi : qu'il manque de
l'encapsulation. Parce que je ne vois pas pourquoi l'auteur de
localtime (chez Microsoft ou Sun) doit avoir besoin de lire la
documentation de mes classes.



On s'est très mal compris. Mon exemple de jour était un exemple dans
*mon* application. Evidemment que je ne demande pas à Microsoft ou Sun
de connaître mes classes Lundi, Mardi, etc.

J'ai pris cet exemple parce qu'il était simple mais tu l'as pris au pied
de la lettre avec sa sémantique alors que *c'était juste un exemple*.

Je ne sais pas si je continuerai à donner des exemples ;-)

Sans rancune James.
Avatar
James Kanze
On Jan 28, 9:48 pm, Wykaaa wrote:
James Kanze a écrit :
> On 27 Jan, 23:09, Wykaaa wrote:
>> James Kanze a écrit :
La plupart des switches sur des enums qu'on trouve en C
devrait se traduire par de l'héritage et du polymorphisme en
C++. Quand on a des imbrications de switches dans des
programmes C, ça correspond, en général, à une vraie
hiérarchie qu'on exprime par de l'héritage et du polymorphisme
en C++.



Ça, je n'en sais rien ; on peut simuler le polymorphisme de
cette façon en C, mais d'après mes souvenirs, c'était peu
fréquent ; la plupart des enums servaient exactement comme ils
servent en C++ : pour représenter une information.

Aussi : on parle ici de C++, non de C. Ce qui se fait en C n'a
que peu d'importance.

> Mais l'enum sert surtout à transporter l'information entre
> des couches de programmation qui ne se connaissent pas,
> d'une façon simple et efficace. Il transporte l'information
> ; il n'a pas de comportement.



Si tu utilises les enums seulement pour faire du transport
d'information et que tu n'as aucun comportement attaché, alors
je ne suis pas contre ce genre d'utilisation, au contraire.



Mais c'est ce que fait un enum. Un enum n'a pas plus de
comportement qu'un int. Moins, même, puisqu'il ne supporte pas
les opérations arithmétique.

[...]
>> 2) polymorphisme



>> class Jour
>> {
>> public:
>> virtual void travailler()=0;



Je n'ai pas relevé précédement, mais qu'est-ce que
« travailler » a à voir avec « Jour » ? Soit les noms n e
conviennent pas, soit il y a une erreur de conception, parce
qu'un jour de la semaine ne travaille pas.

[...]
> Le premier, de loin. C'est un exemple type où l'enum convient,
> et la classe polymorphique non. Parce que le code qui convertit
> la date système en jour ne doit rien savoir de ton travailler,
> même pas qu'il existe.



Le code qui convertit la date système en jour n'a pas à
appeler la fonction travailler(), ça je te l'accorde et même,
si elle le fait, c'est un défaut de dépendance (fort couplage
!).



Exactement.

> Ensuite, si tu as des dépendences dans le comportement, on
> pourrait imaginer une hièrarchie qui les encapsule. Quelque
> chose du genre :



> class Activité
> {
> public:
> virtual ~Activité();
> virtual void travailler() = 0;
> };



> class ActivitéDeJourDeLaSemaine : public Activité ...
> class ActivitéDeSamedi : public Activité ...
> class ActivitéDeDimanche : public Activité ...



> ActivitéFactory* dispatch[] =
> {
> &activitéDeJourDeLaSemaineFactory,
> &activitéDeJourDeLaSemaineFactory,
> &activitéDeJourDeLaSemaineFactory,
> &activitéDeJourDeLaSemaineFactory,
> &activitéDeJourDeLaSemaineFactory,
> &activitéDeSamediFactory,
> &activitéDeDimancheFactory
> };



> std::auto_ptr< Activité >
> getActivité( JourDeLaSemaine jour )
> {
> return dispatch[ jour ]->createInstance();
> }



Cela est trop compliqué et non maintenable.



Au contraire. Il met l'information sur le fait qu'il y a un
comportement spécifique associé au jour là où il doit se
trouver : où il y a un comportement. Et non dans des modules qui
n'ont rien à faire là dedans.

En plus tes classes "ActivitéDe..." sont orientées traitement
et pas objet.



Peut-être. Qu'importe. Elles resoudent le problème d'une façon
simple, élégante, et facilement maintenable.

Aurais-tu fait du SART auparavant ?



Peut-être. Je ne connais pas l'acronyme. (Je ne suis pas très
fort en acronymes.)

Les "Activités" doivent forcément être des méthodes de classe
et non des classes encapsulées dans des objets qui
représentent les entités du domaine de l'application.



Ce sont les activités qui sont polymorphique, non les jours.
L'activité n'est un caractèristique du jour que dans un contexte
très limité.

> Évidemment, le jour qu'on change le nombre de jours dans la
> semaine, il va falloir retoucher le tableau. Mais c'est une
> risque acceptable, à mon avis. Et en fait, ça serait
> probablement toujours moins de travail que ta solution,
> parce qu'on peut supposer que le jour qu'on ajoute, c'est un
> jour de semaine, et donc, la classe nécessaire est déjà
> écrite.



> Dans l'ensemble, je crois que tu as bien mal choisi ton exemple.



Non, il est bien choisi sauf pour le cas où on va ajouter des
sous-classes. A moins qu'on change radicalement le calendrier
en inventant un nouveau jour comme jacadi :-) (Jacques est mon
vrai prénom...).



Et à moins que tu veux une encapsulation qui fait que les
modules qui calculent les jours ne soient pas intîmement couplée
avec les modules qui effectuent du travail qui dépend du jour.

--
James Kanze
Avatar
Mickaël Wolff
Stan a écrit :


Prenons un cas concret: interprétation d'un protocole applicatif
'lambda'.
Dans une trame, tu as un champ type :
- 0x1 : message d'état
- 0x2 : message de supervison
- 0x3 : alarme(s) systeme
- 0x4 : etc.

la suite du champ type contient les paramètres.

Comment utilises-tu ton exemple ?

--
-Stan





struct factory
{
template <Typename MessageT>
void create(<std::auto_ptr<machin> & truc) ;

} ;

Mais ça ne répond au problème que s'il n'y a qu'un message. Si la
construction de l'objet dépend d'un contexte, on peut imaginer
encapsuler ce contexte et le fournir à la factory. Mais à ce moment on
risque effectivement d'avoir un switch dans le create. Là je ne saurais,
de mon petit niveau, apporter une solution élégante.

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
4 5 6 7 8