300

Bon, je suis à peu près à la moitié de mon bouquin, et j'ai une question.
Dans le cadre d'une classe possédant un ou des espaces alloués par new, est-il bon d'avoir toujours ce que l'auteur appelle une classe canonique, c'est à dire avec au minimum constructeur + destructeur (ça ok c'est normal), mais aussi un constructeur de copie et un opérateur d'affectation ('=' surchargé) ? Ca me semblerait normal que ce soit toujours le cas, non ? Je me trompe ?
Ce serait de toute façon une sécurité en cas de création d'un objet temporaire (par exemple, dans le cas d'un passage par valeur) ?

ps -> dans le cas d'un passage par référence, est-ce que la fonction appelée travaille directement sur l'objet argument, ou sur une copie, copiée après dans l'objet initial ? On serait alors dans le cas d'utilisation du constructeur de copie.

301

Le constructeur de copie et l'opérateur = ça sert que quand tu manipules des champs non simplement duplicables (typiquement: pointeurs), sinon... bof bof quoi.
Et même encore, si tu sais que ton objet ne sera pas utilisé en recopie (tu l'alloueras uniquement avec un new, et jamais autrement, et tu n'aura jamais besoin d'en copier un) alors c'est pas forcément la peine de s'encombrer de ça.
Le passage par valeur, c'est une recopie, c'est un cas où le constructeur par recopie et le = sont strictement nécéssaires (enfin les deux vont ensemble, c'est con de faire l'un sans l'autre).
Enfin, avoir un constructeur de recopie, et opérateur = surchargé ça ne fera jamais de mal (si c'est bien codé wink )... Mais si ça sert a rien, tu fais du code pour la décoration...

Le passage par référence ça fonctionne comme un pointeur déréférencé, pointeur qui ne peut jamais être NULL et dont tu peux pas modifier la valeur. (Mais tu peux la connaître avec un bête & comme d'hab). En tout cas, ça veut dire pas de recopie.
Il n'y a qu'un seul truc fourbe, tu peux facilement passer par référence des objets construits de manière temporaire.
ssiner...
Exemple: Dessiner(const Rectangle& rect); // Prototype
Dessiner(Rectangle(0, 0, 10, 10)); // Dans ce cas, Rectangle est un objet temporaire, dont tu fileras la référence à De

Si tu ne fais pas gaffe et que tu stockes quelque part la référence, ou le pointeur (l'un ou l'autre on s'en fout) vers cette valeur temporaire, dans le but de l'utiliser plus tard, c'est plantage assuré oui
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

302

Je galère avec ça, pourtant la POO, je pige, enfin je crois, au point d'être perdu sans.

Comment tu copies, ou modifies, une instance de classe en POO pure? (Disons en Java ou C#, car le C++ c'est bien trop complexe pour moi, désolé Folco du coup de polluer ton topic) :

Puisque on ne référence que l'adresse mémoire. (façon pointeur en somme)
J'ai pas l'exemple en tête, mais cet après midi, j'ai essayé de modifier l'instance venant d'un List<mon_objet> et bien sur je ne modifiais pas l'objet... Bon je fais comme si j'y étais, et désolé de faire de la merde :

foreach (MyObject objet in maListeDeMyObject)
{
objet.MonAssesseur = 5:
}

Si je cherche dans maListeDeMyObject une instance dont MonAssesseur vaut 5, je ne le trouve pas... (évidemment allez vous me dire)
D'après mon chef, c'est logique, d'après moi, j'ai RIEN pigé à la POO alors que je ne fais que ça...

Humblement, HELP!

303

Tu appelles une fonction pour ça ?

304

obj. ?

ça devrait pas plutot etre

objet. ?
avatar
Proud to be CAKE©®™


GCC4TI importe qui a problème en Autriche, pour l'UE plus et une encore de correspours nucléaire, ce n'est pas ytre d'instérier. L'état très même contraire, toujours reconstruire un pouvoir une choyer d'aucrée de compris le plus mite de genre, ce n'est pas moins)
Stalin est l'élection de la langie.

305

./302 Il faudrait que tu précises ton problème (quel langage, etc.) parce que ça peut venir d’un petit détail tout con.
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

306

GoldenCrystal (./301) :
Le passage par référence ça fonctionne comme un pointeur déréférencé, pointeur qui ne peut jamais être NULL et dont tu peux pas modifier la valeur.

Bah si ça peut être nul embarrassed
int &i = *(int*)0;
cout << i;  // crash

Et "modifié" embarrassed
int i = 1, j = 2;
int &k = i;
{
    int &k = j;
    cout << k;   // 2
}
avatar
Highway Runners, mon jeu de racing à la Outrun qu'il est sorti le 14 décembre 2016 ! N'hésitez pas à me soutenir :)

https://itunes.apple.com/us/app/highway-runners/id964932741

307

Godzil > t'as raison, je corrige mon post.

Sasume > En C#.

Folco > Non , pas de fonction, les majuscules c'est une convention dans ma boite pour les assesseurs et les méthodes publiques. (si c'est ce qui t'as fais penser ça?)

308

En C# il faut voir ce que fait ton accesseur alors... Il a bien la forme suivante?
private int monAccesseur;
public int MonAccesseur {
    get { return monAccesseur; }
    set { monAccesseur = value; }
};

Sinon c'est normal que tu ne voies pas la modif wink
avatar
Highway Runners, mon jeu de racing à la Outrun qu'il est sorti le 14 décembre 2016 ! N'hésitez pas à me soutenir :)

https://itunes.apple.com/us/app/highway-runners/id964932741

309

./306
1. love Vive le C++
2. Mouais, je n’ai peut-être pas bien compris, mais dès qu’on sort du bloc l’identificateur « k » correspond de nouveau à la référence vers i, non ? (les deux k sont des variables différentes, et pas une variable qui a été modifiée)
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

310

Ben oui c'est ça Brunni.
Mais ça m'énerves de ne pas comprendre pourquoi dès que c'est dans un foreach de List<> je n'ai accès qu'à l'adresse mémoire, ou plutôt une copie de l'instance.
"Littéralement" (for each) je fais bien une boucle sur chaque élément de la liste?

311

Sasume (./309) :
./306
1. love Vive le C++
2. Mouais, je n’ai peut-être pas bien compris, mais dès qu’on sort du bloc l’identificateur « k » correspond de nouveau à la référence vers i, non ? (les deux k sont des variables différentes, et pas une variable qui a été modifiée)

Yep pour le 2. pour une fois le C++ est bien fait, y a vraiment pas moyen de modifier une référence il me semble.
Mais avec un deuxième bloc imbriqué c'est facile de se planter (ça m'est arrivé y a pas longtemps) donc ça passe aussi grin
avatar
Highway Runners, mon jeu de racing à la Outrun qu'il est sorti le 14 décembre 2016 ! N'hésitez pas à me soutenir :)

https://itunes.apple.com/us/app/highway-runners/id964932741

312

GUNNM (./310) :
Ben oui c'est ça Brunni.
Mais ça m'énerves de ne pas comprendre pourquoi dès que c'est dans un foreach de List<> je n'ai accès qu'à l'adresse mémoire, ou plutôt une copie de l'instance.
"Littéralement" (for each) je fais bien une boucle sur chaque élément de la liste?

Oui. Et objet est une référence vers MyObject, donc tu dois pouvoir modifier l'objet. Quel est le type de MyObject? Si c'est un struct ou un autre type par valeur, alors ça fonctionne par copie.
avatar
Highway Runners, mon jeu de racing à la Outrun qu'il est sorti le 14 décembre 2016 ! N'hésitez pas à me soutenir :)

https://itunes.apple.com/us/app/highway-runners/id964932741

313

Le foreach ça permet d'énumérer, autrement dit d'accéder aux valeurs contenues dans la liste, mais pas de modifier la liste.
Donc si ton contenu est fait de références (types références), tu pourra modifier les instances des objets en tant que tel (modifier une instance ça se fait en utilisant les champs, propriétés et méthodes de cette instance), mais si ton contenu est fait de valeurs (types valeurs, donc tout ce qui est dérivé de System.ValueType) comme par exemple dans le cas d'une List<int>, ben tu obtiendras la valeur de chaque élément tout pareil, sauf qu'une valeur ici ça va être par exemple 3. Et y'a aucune propriété à modifier sur une valeur telle que 3... La seule chose à modifier ça serait la valeur en elle-même, mais modifier ça, ça serait donc modifier la liste, ce qui n'est pas le but de l'énumération.
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

314

Brunni (./306) :
GoldenCrystal (./301) :
Le passage par référence ça fonctionne comme un pointeur déréférencé, pointeur qui ne peut jamais être NULL et dont tu peux pas modifier la valeur.

Bah si ça peut être nul embarrassed
int &i = *(int*)0;

Cette ligne n'est pas du C++ valide, c'est interdit par le standard.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

315

Brunni (./306) :
Et "modifié" embarrassed
int i = 1, j = 2;
int &k = i;
{
    int &k = j;
    cout << k;   // 2
}
k n'est pas modifié, il est juste masqué par une autre référence du même nom pendant la duré du bloc.
avatar

316

Kevin Kofler (./314) :
Brunni (./306) :
int &i = *(int*)0;

Cette ligne n'est pas du C++ valide, c'est interdit par le standard.

Je vois pas pourquoi ce serait interdit? confus Je viens de tester et mon compilo l'accepte en tous cas.
Uther (./315) :
k n'est pas modifié, il est juste masqué par une autre référence du même nom pendant la duré du bloc.

Je sais, je l'ai déjà dit plus haut, mais pour m'être déjà fait avoir par ça faut faire gaffe quand même ^^
avatar
Highway Runners, mon jeu de racing à la Outrun qu'il est sorti le 14 décembre 2016 ! N'hésitez pas à me soutenir :)

https://itunes.apple.com/us/app/highway-runners/id964932741

317

*retour svp smile*

Bon, ya un truc qui me tracasse depuis 100 pages au moins.

Si on a une classe MaClasse et une instance MonObjet de cette classe, alors :
MaClasse MonObjet_2 = Mon_Objet;
appellera le constructeur de copie si celui-ci est défini ? De la même manière que si l'on passait MonObjet en paramètre ou en retour de fonction ?

Alors à quoi sert de surcharger éventuellement '=' pour obtenir un opérateur d'affectation ? Uniquement pour le cas où l'on affecterait MonObjet à un autre objet MaClasse déjà instancié ?

J'avoue que je suis un peu embrouillé...

318

Il y a un constructeur de "copie" en C++ ??
avatar
Proud to be CAKE©®™


GCC4TI importe qui a problème en Autriche, pour l'UE plus et une encore de correspours nucléaire, ce n'est pas ytre d'instérier. L'état très même contraire, toujours reconstruire un pouvoir une choyer d'aucrée de compris le plus mite de genre, ce n'est pas moins)
Stalin est l'élection de la langie.

319

Folco (./317) :
Si on a une classe MaClasse et une instance MonObjet de cette classe, alors :
MaClasse MonObjet_2 = Mon_Objet;appellera le constructeur de copie si celui-ci est défini ?
Oui.
De la même manière que si l'on passait MonObjet en paramètre ou en retour de fonction ?
Oui (dans le cas d’un passage par valeur, bien sûr wink )
Alors à quoi sert de surcharger éventuellement '=' pour obtenir un opérateur d'affectation ? Uniquement pour le cas où l'on affecterait MonObjet à un autre objet MaClasse déjà instancié ?
Oui.
Complex x(1, 2); // x = 1 + 2i
Complex y(2, 3); // y = 2 + 3i

if(x.module() > y.module()) {
  x = y;
}
(flemme de chercher un exemple vraiment utile)
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

320

Sasume (./319) :
Oui (dans le cas d'un passage par valeur, bien sûr wink.gif )

Oui bien sûr.

Bon ben cool, j'ai compris ! \o/

Merci. smile

321

Sasume (./319) :
De la même manière que si l'on passait MonObjet en paramètre ou en retour de fonction ?
Oui (dans le cas d’un passage par valeur, bien sûr wink )
C'est sur pour le cas des valeur de retour ? Normalement ça doit pas *systématiquement* provoquer de recopie non ? confus

Pour le reste > pencil (et ton exemple est très bien tongue)
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

322

D'après mon bouquin, on est dans la même situation avec un argument passé par valeur et une valeur de retour, oui.

323

Ouais. D’ailleurs ça fait qu’il faut être prudent et ne pas écrire ce genre de choses :
Type & fonction() {
  Type objet;

  return objet;
}


Car l’objet ne sera pas copié, c’est bien son adresse qui sera transmise, et comme il a été alloué sur la pile, il ne va pas tarder à se faire écraser…
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

324

oui, mon bouquin met en garde contre ça aussi.

325

Ça c'est pas un problème, normalement le compilateur émet un warning quand il sait que tu as probablement fait de la merde ^^
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

326

Pas une raison, toute façon ça marchera pas ^^

327

(Ah, ça rien ne te le dit !)
Sinon, pour les valeurs de retour, j'ai trouvé: http://en.wikipedia.org/wiki/Return_value_optimization
Je savais bien que c'était pas une obligation ! tongue
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

328

cross, vous avez tous répondu grin
Sasume (./319) :
Folco (./317) :
Si on a une classe MaClasse et une instance MonObjet de cette classe, alors :
MaClasse MonObjet_2 = Mon_Objet;appellera le constructeur de copie si celui-ci est défini ?
Oui.

Et s'il n'est pas défini, c'est le constructeur de copie par défaut qui sera appelé, qui appelle lui-même le constructeur de copie de chacun des membres de ta classe. En gros c'est une copie bit à bit sauf si tu définis ton propre constructeur de copie.

Je ne sais pas trop s'il y a un cas où le compilateur peut appeler le constructeur sans paramètres puis l'opérateur =, mais je pense pas
GoldenCrystal (./321) :
C'est sur pour le cas des valeur de retour ? Normalement ça doit pas *systématiquement* provoquer de recopie non ? confus

non, c'est pas systématique, le compilateur peut optimiser en filant à la fonction qui renvoit par valeur l'adresse mémoire où la fonction devra créer son objet. cette adresse pointera dans la pile de la fonction appelante par exemple
plus de détails : http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.9
avatar

329

aze (./328) :
En gros c'est une copie bit à bit sauf si tu définis ton propre constructeur de copie.

Une copie memberwise depuis la norme, mais c'était bitwise avant. Ceci dit, je peux pas te dire ce que ça change grin #étale_sa_science_tout_nouveau_tout_beau#

330

je ne vois pas trop la différence confus
la copie membre-à-membre se fera bit-à-bit s'il n'y a pas de constructeur de copie défini pour ce membre
avatar