CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

(c++) Problème de surcharge d'operateurs

lag-it
lag-it
Niveau 10
04 mai 2004 à 20:40:07

J´ai créé une classe Vector qui comprends nottament comme fonctions membres :

/ / Add ( without modification )
Vector operator+( const Vector & )
{ return Vector( x+src.x, y+src.y, z+src.z ) ; }
// Add ( with modification )
Vector operator+=( const Vector & )
{ x+=src.x; y+=src.y; z+=src.z; return *this; }

// Sub ( without modification )
Vector operator-( const Vector & )
{ return Vector( x-src.x, y-src.y, z-src.z ) ; }
// Sub ( with modification )
Vector operator-=( const Vector & )
{ x-=src.x; y-=src.y; z-=src.z; return *this; }

( les fonctions sont inlkine dans le . h, d´ou l´absence de " Vector::" )

Mais losrque j´exécute le programme suivant :

  1. include < iostream>
  1. include " vector.h"

using namespace std;

int main( void )
{
Vector v1( 18.0, 20.0, 78.0 ) , v2( 2.0, 51.0, 27.0 ) ;

cout < < ( v1+v2).x < < " " < < ( v1-=v2).x < < endl;

return 0;
}

J´obtiens " 18 16", alors que si je supprime la partie ( v1-=v2).x, et que je ne garde que ( v1+v2).x, j´obtiens bel et bien " 20". Plusieurs combinaison de ce type produisent des résultats fantaisistes, pourquoi ? Le problème semble venir desopérateurs += et -=...

LGV
LGV
Niveau 28
04 mai 2004 à 21:02:00

il faudrait vérifier dans le standard, mais je crois que ton expression melangeant + et -= a un comportement non défini. Donc trace au debugger pour vérifier, mais je pense qu´avec ton compilo v1 -= v2 est évalué en premier, du coup v1.x devient 16, et ensuite v1 + v2 est évalué, qui vaut alors 18.
avec un autre compilo qui évaluerait dans un autre ordre le résultat pourrait etre différent.
procède pas étape élémentaire pour lever toute ambiguité.

lag-it
lag-it
Niveau 10
04 mai 2004 à 21:06:02

Pourtant j´utilise Visual C++ . net 2002.

Mais pourquoi exécuterais il -= avant le + ?
Il effectue un appel d´opérateurs en cascades, donc le + est traité avant le -= théoriquement...

LGV
LGV
Niveau 28
04 mai 2004 à 21:12:32

" Il effectue un appel d´opérateurs en cascades, donc le + est traité avant le -= théoriquement..."

ben non, ça n´a rien de sûr du tout ça justement ; l´ordre d´évaluation ne correspond généralement que peu à l´ordre d´apparation dans le code, ça peut aussi dépendre d´option de compilation : à moins de faire les calls à main en asm, c´est pas évident du tout.
vu que c´est variable d´un compilo à l´autre, on évite d´utiliser les expressions faisant intervenir une variable et la meme modifiée.
trace au debugger pour vérifier l´ordre d´appel.
avec des pre/post ++/-- et des = on fait souvent des expressions qui peuvent donner des résultats variables selon l´évaluation ; une seule façon de procéder, découper les calculs sur plusieurs lignes pour etre sûr de l´ordre.

lag-it
lag-it
Niveau 10
04 mai 2004 à 21:17:09

C´est bizarre...

Quand on surcharge l´opérateur de sortie standard, on fait souvent :

ostream &<<( ostream &, . .. )
{
sortie < < . .. ;
return sortie;
}

Qui implique que les expreesions soient traiter dans l´ordre de leur écriture.
Les types standard n´utiliseraient donc pas ce schéma ?

kufa
kufa
Niveau 9
04 mai 2004 à 22:03:04

Qui implique que les expreesions soient traiter dans l´ordre de leur écriture.

Nope pas du tout: ( extraits de la doc iso c++)

" Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified. "

hs_dino
hs_dino
Niveau 9
04 mai 2004 à 22:03:36

Lag-it, c´est tres dangereux de faire çà. L´ordre de resolution d´une expression dépend totalement du compilateur et n´est absolument pas normalisé, je te conseil donc vivement de ne jamais utiliser les operateur += -= / = *= de la sorte car tu auras a coup sur des surprises.

Autre chose qui n´a rien a voir, je te conseile de retourner une référence à chaque fois que tu retourne *this

ex: Vector& operator-=( const Vector & )
{ x-=src.x; y-=src.y; z-=src.z; return *this; }

Ensuite, pour tes operateurs ´Without modification´, déclare les en ´friend´, ca parait plus coherent, car une fonction qui ne traite que des parametres sans meme utiliser sont contenu n´a aucun sens en C++.

Voilà, j´espere que çà pourra t´aider :)

Ca parait bete, mais tu viens d´éviter d´alouer Vector en pile pour le copier et le detruire aussitot dans ton parametre de retour.

hs_dino
hs_dino
Niveau 9
04 mai 2004 à 22:06:18

:d) Petite erreur de dactylo :)

Lag-it, c´est tres dangereux de faire çà. L´ordre de resolution d´une expression dépend totalement du compilateur et n´est absolument pas normalisé, je te conseil donc vivement de ne jamais utiliser les operateur += -= / = *= de la sorte car tu auras a coup sur des surprises.

Autre chose qui n´a rien a voir, je te conseile de retourner une référence à chaque fois que tu retourne *this

ex: Vector& operator-=( const Vector & )
{ x-=src.x; y-=src.y; z-=src.z; return *this; }

Ca parait bete, mais tu viens d´éviter d´alouer Vector en pile pour le copier et le detruire aussitot dans ton parametre de retour.

Ensuite, pour tes operateurs ´Without modification´, déclare les en ´friend´, ca parait plus coherent, car une fonction qui ne traite que des parametres sans meme utiliser sont contenu n´a aucun sens en C++.

Voilà, j´espere que çà pourra t´aider

lag-it
lag-it
Niveau 10
04 mai 2004 à 22:08:55

kUfa > Oui, c´est pour ca que je demandais si les opérateurs standard suivaient ce schéma.

HS_DIno > C´est noté pour le renvoi de référence.
Sinon les without modification, pourquoi les déclarer en friend ? Je ne connais pas trop l´usage de ce mot-clé, hormis dans la surcharge des opérateurs à droite.

Merci à vous :)

LGV
LGV
Niveau 28
04 mai 2004 à 22:16:27

opérateurs friend ou pas, débat sans fin, y´a les partisans, y´a les opposants :/
moi je suis plutôt " pas friend", les membres de l´objet étant utilisés dans le corps de l´opérateur, mais c´est surtout question de préférence il me semble.
Enfin si qqun voit un réel avantage à utiliser des op. friend, ou l´inverse, je suis tout ouïe.

sinon, pour les += -= " with modifications", j´ai plutôt tendance à returner void, c´est pas forcément plus contraignant et ça évite d´enchainer des expressions avec problème éventuel d´éval, comme dans l´ex. de lag-it.
là encore, tous les points de vue se défendent.

lag-it
lag-it
Niveau 10
04 mai 2004 à 22:20:57

" Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified."

Quelqu´un pourrait éclaircir ce passage ?
Car j´ignorais cette partie de la norme ( je connais bien celle du C, mais peu celle du C++ )

kufa
kufa
Niveau 9
04 mai 2004 à 22:30:22

Oui, c´est pour ca que je demandais si les opérateurs standard suivaient ce schéma.

Tout depends du compilo, vraiment..

Sinon perso ++"pas friend", sauf quand vraiment necessaire, surtout pour des pbs de design ( je vous conseille le c++ faq lite)

LGV
LGV
Niveau 28
04 mai 2004 à 22:30:25

ben ça dit exactement ce qu´on a expliqué, que l´ordre d´évaluation des opérateurs ou sous-expressions n´est pas défini par le standard ; ça reste donc " compilo dépendant".
Il faudrait voir les cas précisés par la norme, puisqu´il est dit " except where noted" . ..

kufa
kufa
Niveau 9
04 mai 2004 à 22:35:39

Je vous laisse regarder ( pas le temps moua ; )
http://www.kuzbass.ru/docs/isocpp/
dans la partie expressions

lag-it
lag-it
Niveau 10
04 mai 2004 à 22:46:38

Merci, j´irai voir ca.

Sinon j´ai un petit truc qui me chagrine :

J´ai créé une classe Vector et une classe Vertex et je fournis à chacune 3 constructeurs : 1 avec des ccordonnées float, l´autre avec un Vector ou un Vertex ( constucteur de copie ) et un dernier permettant de convertir un Vector en Vertex et un Vertex en Vector.
Ca donne ca pour le Vertex :

Vertex( const Vector & )
{ x = src.x; y = src.y ; z = src.z; }

Ca ne pose aucun problème pour la création d´un Vector à partir d´un Vertex, mais dans le cas de la création d´un Vertex à partir d´un Vector ( cas plus haut ) , le compilateur refuse de compiler mon fichier et me sort :

error C2334: jetons inattendus avant ´{´ ; corps apparent de la fonction ignoré
error C2629: ´Vertex ( ´ inattendu

Sachant que :

[Compiler Error C2334]

" jetons inattendus avant ´: ou {´; corps apparent de la fonction ignoré"

Cette erreur se produit après une autre erreur, pour les fonctions membres définies dans leur classe.

Exemple

/ / C2334.cpp
struct s1 { / / in a cpp file
s1(s1 func hello) { / / C2334
}
};

[Compiler Error C2629]

´token ( ´ inattendu

Une erreur de syntaxe rend l´instruction ambiguë.

Cause possible

Mélange de syntaxe de déclaration et d´expression.
Exemple

/ / C2629.cpp
class A
{
};

class B
{
public:
int ( A::*apmfi)(), ( A::*apmfi2)();
};

int ( (A::*)(B::*)bpmapmfi)() = &::apmfi; / / C2629

Et ce, même en utilisant une déclaration préliminaire " class Vector;"
Qu´est ce qui ne va pas ?

kufa
kufa
Niveau 9
04 mai 2004 à 23:09:43

Tu mets le corps des constructeurs dans le . hpp?

lag-it
lag-it
Niveau 10
04 mai 2004 à 23:10:39

Non, dasn un . h classique.

kufa
kufa
Niveau 9
04 mai 2004 à 23:56:04

Les . h/.hpp sont des headers, mais bcp de personnent ont la mauvaise habitude de mettre le corps des fonctions dans ces headers. Du coup, une modif dans le . h, et hop faut recompiler tous les . c qui incluent ce . h....

Ex de qqchose qui ne peut pas fonctionner:

class B;

class A
{
public:
void toto( B& test )
{
cout < < B.valeur; / ** erreur */
}
};

class B
{
public:
int valeur;
};

Par contre ca ca fonctionnera:

/ ** dans le . hpp */

class B;
class A
{
public:
void toto( B& test ) ;
};

class B
{
public:
int valeur;
};

/ ** dans le . cpp */

void A::toto( B& test )
{
cout < < B.valeur;
}

hs_dino
hs_dino
Niveau 9
05 mai 2004 à 00:06:47

friend a l´avantage de permettre de fonctionner quelque soit l´ordre.

Ex : Si tu veux multiplier un veteur par un scalaire :

Vector v(1,2,3),a;
float s = 4;

a = v * s; / / fonctionne si Vector::operator*(float)
a = s * v; / / fonctionne pas car le float est a gauche !

Mais grace au friend:

friend Vector::operator(Vector, float)

Et ca ca marche pour les deux cas situé plus haut. Ca sert a çà le friend, c´est absolument pas une histoire de bien ou de pas bien, ou de propre ou de pas propre, ou de j´aime ou j´aime pas, c´est juste que c´est comme çà qu´il faut faire sinon ca marche pas ! :)

hs_dino
hs_dino
Niveau 9
05 mai 2004 à 00:09:28

oui j´ai oublié de préciser que si je fais mon malin avec mes ´friend´ c´est juste parce que je l´ai appris le mois dernier a l´école, sinon j´etais comme vous je n´utilisais jamais ce mot clé : trop caca quand on ne sait pas l´utiliser ! :ok:

Sous forums
  • Aide à l'achat Mac
  • Internet
  • Macintosh
  • Création de sites web
  • Création de Jeux
  • Linux
  • Programmation
  • Steam Deck
  • Hardware
La vidéo du moment