210

Pen^2 (./207) :
Cela dit c'est vraiment vilain, c'est quand même utile de savoir si on modifie la source ou pas en lisant l'implémentation

Mais c'est clair, là où tu crois appeler une fonction en passant des valeurs, tu vas te retrouver avec des variables modifiées. C'est casse-gueule...

211

Folco (./206) :
Bon ben ça foire à la compilation, et c'est logique pour la raison que je pensais : on ne peut avoir, dans fact, une référence à n de main :

C'est pas exactement ça, c'est que si tu lui passes n - 1 il ne peut pas convertir ça en référence.
(même si en théorie il pourrait te passer une référence vers l'objet temporaire qu'a généré l'opération n-1)
Ca devrait marcher ça normalement:
int fact(int &n) {
    if (n >= 1) {
        n--;
        return (n + 1) * fact(n);
    }
    else
        return 1;
}

int main() {
    int x = 10;
    std::cout << fact(x) << std::endl;
}
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

212

je te conseille d'utiliser les références, mais :
– de bien spécifier le passage par référence dans les définitions en plus des déclarations
– de passer des références const quand la valeur ne doit pas être modifiée. Une référence non const doit être considérée comme une valeur retournée par la fonction


Au passage, ajoute aussi le nom du paramètre dans ta déclaration, sinon, on ne sait pas ce qu'on passe en lisant le .h wink
(ça ne te dispense pas d'écrire la doc, c'est complémentaire tongue)

213

Pen^2 (./207) :
Si tu le dis... Cela dit c'est vraiment vilain, c'est quand même utile de savoir si on modifie la source ou pas en lisant l'implémentation

C'était ... euh... une blague cheeky

Par contre, c'est dans l'appel qu'on ne rappelle rien, ce qui garde bien le côté casse-gueule
C'est pas exactement ça, c'est que si tu lui passes n - 1 il ne peut pas convertir ça en référence.

Oui t'as raison, mon diagnostic était faux. Ta solution est la bonne. oui

214

quelle blague ?
tu écris tes déclarations en spécifiant le passage par référence, et tes définitions, non.
moi j'ai toujours écrit le & dans les deux

215

C'est moi qui ait fait la "blague" (en fait la bourde grin) de dire que c'était facultatif dans l'implémentation grin

c'est bon, j'ai écrit ma version, mais avec une variable intermédiaire :
using namespace std;

int fact(int &);

int main()
{
    int n = 5;
    cout << fact(n);
}

int fact (int & n)
{
    int a = n-1;
    if (n == 1)
        return 1;
    else
        return n * fact(a);
}

C'est marrant ces espèces de pointeurs qu'on manipule comme des types scalaires ^^

216

OK
J'ai cru un moment que le c++ était encore plus chiant que ce que je pensais grin
Cela dit, pour les méthodes statiques, il faut spécifier qu'elles sont statiques dans la déclaration, mais pas dans l'implémentation tritop (il y a peut-être une raison, mais c'est vilain, ça aussi)

217

Ah ? Alors dis-moi où, je suis tout à fait preneur, je vois pas trop ce que tu veux dire. smile
ok, tu parlais pas de mon code couic

218

oué j'ai édité furtivement, c'était pas clair tongue

zzz

219

Note que ta version n'est pas tout à fait équivalente à la mienne Folco: dans ton cas tu réserves une nouvelle variable sur la pile et tu passes une référence vers celle-ci à chaque appel, alors que dans mon cas je passais la même référence à la variable de base.
Du coup ta version n'a pas l'effet de bord de modifier n, mais ce n'est pas non plus utile de le passer en référence 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

220

Anéfé.

221

Pen^2 (./216) :
Cela dit, pour les méthodes statiques, il faut spécifier qu'elles sont statiques dans la déclaration, mais pas dans l'implémentation tritop.gif (il y a peut-être une raison, mais c'est vilain, ça aussi)


static dans l'implémentation => sémantique C et fonction visible dans le fichier uniquement
static dans la classe: =>sémantique objet java toussa membre de classe et pas d'instance.
fail.
Folco (./215) :
C'est marrant ces espèces de pointeurs qu'on manipule comme des types scalaires ^^

pour moi c'est plutot au maximum DO NOT WANT fear c'est tellement facile à utiliser que pour moi c'est trop casse gueule, j'aime pas les langages champomy ou les pointeurs ont le gout du champagne sans en être. (mais bon , une grande partie de qt est basée la dessus, alors faut s'y faire sad, mais j'aime pas manipuler des trucs en sachant que CE SONT des pointeurs (bah si... mais cachés), mais que le compilo fera ce qui lui semble cool pour transformer ça en trucs qui passeront dans des pointeurs sans me le montrer fatigue fou3 #treeek#

222

Attention, les objets implicitement partagés de Qt ont quand-même un comportement très différent des simples références dont il est question ici. Et Qt ne cache les pointeurs que quand il ne s'agit que d'un détail d'implémentation qui n'a aucun effet sur le comportement. Par exemple, un QString (implicitement partagé) se comporte comme un simple int, c'est juste que la copie est retardée jusqu'à la première écriture, ce qui évite de recopier un gros objet pour rien. Mais un objet qui représente un vrai objet avec un comportement (ou, ce qui est équivalent dans la logique de Qt: avec des évènements (signaux et/ou slots)), pas de simples données, est toujours traîté comme un pointeur. (QObject n'est volontairement pas implicitement partagé!) Et Qt évite le passage par référence non-const, parce que ça cache le fait que la fonction a accès au pointeur et peut modifier la variable, alors que const & est utilisé souvent en tant qu'optimisation qui ne change pas la sémantique.
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é

223

Il y a un endroit ou Qt utilise les références et ou il aurait bien du s'en garder, c'est dans l'API de Collection de Qt. J'ai longtemps galéré avec, finalement j'ai abandonné, je ne m'en sert plus que pour y mettre des pointeurs.
avatar

224

225

Je ne vois pas trop de quoi tu parles. Le seul endroit où il y a des références non-const (j'ai déjà expliqué l'histoire des const &), c'est comme valeur de retour des fonctions comme operator[], ce qui permet d'écrire le classique liste[idx]=toto;, et de même liste.first()=toto est permis. Et si tu utilises les fonctions en lecture seule, que ce soit une référence ou une valeur n'a aucune importance.
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é

226

folco > la fonction peut fonctionner sans variable temporaire, mais il faut utiliset une ref const :
int fact (const int &n) 
{ 
    if (n == 1) 
        return 1; 
    else 
        return n * fact(n-1); 
}

le compilateur ne peut pas créer une référence non-const sur n-1 car ce n'est pas une variable modifiable mais une valeur (il me semble que c'est équivalent aux problèmes de r-value et l-value que tu as déjà peut-être rencontré en C)

Globalement il faut toujours utiliser des références const quand la fonction ne doit pas modifier le paramètre en entrée. ça t'évitera plein de problèmes de compilation et quand tu rencontreras une fonction qui prend un paramètre non-const tu auras que la fonction est prévue pour modifier le paramètre en entrée
avatar

227

squalyl (./221) :
mais que le compilo fera ce qui lui semble cool pour transformer ça en trucs qui passeront dans des pointeurs sans me le montrer

Toi t'es mûr pour repasser à l'assembleur #modcoquin#

aze -> ah oué, merci. happy

228

Folco: nan merci je peux pas perdre de temps, je reste au C #modui#

229

grin

Sinon, si vous êtes pas trop référence, vous codez alors en C++ avec des pointeurs plutôt, comme en C ? Je croyais que justement, ça faisait partie de ce que vous lui reprochiez, la gestion des pointeurs ? (moim'enfous, j'ai jamais été dérangé par les pointeurs grin)

En fait, c'est marrant une référence : c'est comme si le compilateur savait tout seul si l'on veut parler d'un pointeur ou de sa valeur pointée. hehe

230

avec une référence c'est pas trop dur, tu ne peux pas parler d'autre chose que de la valeur pointée ^^
avatar

231

Ben, si on reprend cet exemple :
exemple
int fact(int &);

int main()
{
    int n = 6;
    cout << fact(n);
}

int fact (int & n)
{
    if (n == 1)
        return 1;
    else
        n--;
        return (n + 1) * fact(n);
}

le "return (n-1)" une valeur, et le n de "*fact (n)" est une référence, donc doit bien pointer sur l'objet initial, non ?

232

"n" est une référence, mais tu t'en fous. quoi qu'il arrive, pour n'importe quel accès à "n", la référence sera dé-référencée. Bon, quand tu passes une référence à une fonction qui prend une référence en entrée, il va juste copier la référence, pas dé-référencer pour prendre la référence derrière ou prendre une référence sur une référence.
D'ailleurs les références à des références n'existent pas : "int i; int &ref_i = i; int &&ref_ref_i = ref_i;" ne compile pas, contrairement au même code avec des pointeurs.

par contre ton code est vraiment très crade, avec plein d'effets de bord de partout.
les références non const pour les paramètres qui ne sont pas de sortie, c'est à éviter absolument !

mais je me suis mal exprimé. plutot que "valeur pointée", j'aurais du dire "objet pointé" (qui est un int dans ton cas), pour être plus exact
avatar

233

Folco (./230) :
Sinon, si vous êtes pas trop référence, vous codez alors en C++ avec des pointeurs plutôt, comme en C ?

pour moi le C++ est du java natif compatible avec le C, je connais rien d'autres et surtout pas les templates, donc j'essaye de faire un code qui ressemble a ce que je connais en java triso

en java: y'a que des int, et des pointeurs vers des objets (sans arithmétique, donc c'est plutot des références mais osef) et j'aime pas la syntaxe moisie des refs c++, donc on peut dire que je "connais" que les pointeurs et le mot clé new (pas de delete en java trilove)

234

aze (./232) :
par contre ton code est vraiment très crade, avec plein d'effets de bord de partout.

Content de te l'entendre dire. smile Un const ne suffit pas alors ? Qu'y a-t-il d''autre stp ?

235

ne pas utiliser de références pour calculer une factorielle grin
pour les paramètres de fonction, il y a en gros deux utilisations des refs :
- les const ref pour éviter la copie des gros objets à chaque appel de fonction. c'est encore plus utile quand la fonction appelée va repasser la ref à une autre fonction qui prend une const ref en entrée. là pour un int ça sera plus couteux de passer par ref que par valeurs
- les ref non-const, pour les paramètres de sortie, c'est à dire dans lesquelle la fonction va renvoyer des valeurs, exemple
void swap(int &a, int &b)
void swap(int &a, int &b)
{
    int &c = a;
    a = b;
    b = c;
}


C'est comme pointeurs passés en paramètres en C, tu as les const et les non-const pour ces deux utilisations.
avatar

236

Merci. smile

237

Folco (./229) :
grin

Sinon, si vous êtes pas trop référence, vous codez alors en C++ avec des pointeurs plutôt, comme en C ? Je croyais que justement, ça faisait partie de ce que vous lui reprochiez, la gestion des pointeurs ? (moim'enfous, j'ai jamais été dérangé par les pointeurs grin)

Plutôt pointeur car les références sont fixées une fois affectées.
Franchement plus je lis tes questions plus je me dis que tu devrais plutôt te mettre au Java pour commencer la POO pure.
Déjà en Java tu ne passes pas les paramètres par référence, mais toujours par valeur, ce qui te garantit l'absence d'effet de bord comme celui de ta fonction Fibonacci.
Ensuite les objets sont toujours des références, i.e.:
// En Java, seule manière possible
Objet o = new Objet();
// En C++, manière équivalente
Objet *o = new Objet;
delete o;
// En C++, par référence
Objet &o = *(new Objet);
delete &o;
// En C++, sur la pile
Objet o;

En C++ en général tu vas utiliser des pointeurs lorsque les objets sont alloués dynamiquement et partagés dans tout le programme. Tu vas utiliser des objets sur la pile lorsqu'ils sont locaux et lorsqu'ils ne sont pas trop coûteux à manipuler (chaque passage par paramètre implique une copie de l'objet!).
Quant aux références en général tu ne les utilises que dans des cas particuliers, puisqu'un objet alloué sur la pile va être détruit automatiquement à la fin de la fonction qui te l'a fourni. Du coup tu ne peux pas garder l'objet pour plus tard, et ton code ressemblera plus à de la prog procédurale. C'est pour ça que c'est surtout pour simplifier la syntaxe (éviter l'* et le ->) et éviter la copie (mauvaises performances) qu'on utilise ça.
En C# les références se font avec le mot clé ref et on les utilise rarement, en Java elles n'existent pas. Donc c'est pour ça que ça ne sert à rien de trop chercher à les utiliser, car ça ne te sera pas vraiment utile pour la suite 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

238

Brunni (./238) :
// En C++, par référence Objet &o = *(new Objet); delete &o;

ça par exemple c'est #trisick# pour moi

239

Ok, merci bien des conseils.
Ceci dit, étant donné que
- je préfère le code compilé en natif que le Java pour le moment
- ça fait 10 jours que je suis dans le C++ et j'ai acheté un bouquin
je vais poursuivre dans cette voie.
Mais si je persévère, je me mettrai sûrement au Java un jour happy

240

Bien sûr, je te disais ça juste pour pas que tu cherches trop dans cette voie. Le C++ a été conçu par des gens bizarres, y a des trucs pas vraiment utiles (ou du moins dont on fait mieux de se passer) et les références en est un exemple à mon avis.
C'est pas pour rien qu'elles n'ont pas été reprises sous leur forme dans les langages plus récents ^^
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