Réalisation de classe de vecteurs sous C++

Résolu/Fermé
hbelaid Messages postés 15 Date d'inscription lundi 27 avril 2009 Statut Membre Dernière intervention 30 janvier 2011 - 8 janv. 2010 à 16:11
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 - 11 janv. 2010 à 23:07
Bonjour à tous,

J'ai un énorme problème avec C++. Je n'ai que quelques notions et je dois réaliser une classe de vecteurs 2D et définir l'addition et la soustraction de deux vecteurs, la négation, le lstinline+ unitaire ainsi que la multiplication d'un vecteur par un scalaire.

Alors voilà, j'ai deux questions:

- Quelqu'un pourrait me définir le "lstinline"??

- J'ai commencé à définir les opérateurs dans le header Vecteur2D.h comme suit:

#include <iostream>

class vecteur{

double x;
double y;

public:
vecteur();

vecteur(double);

vecteur(double _x, double _y);

vecteur& operator=(const vecteur& v);

vecteur & operator+=(const vecteur& v);

vecteur& operator-=(const vecteur& v);

vecteur conj() const; #pour la négation

};


Dans le fichier Vecteur2D.cc, j'ai défini les opérateurs comme suit (selon les indications de mon prof de TP dans un autre exemple):

#include "vecteur.h"

#include <iostream>

vecteur::vecteur(double x, double y)

{
this-> x = x;
this-> y = y;
}


vecteur& vecteur ::operator=(const vecteur& v)

{
this-> x = v.x;
this-> y = v.y;
return *this;
}


vecteur& vecteur ::operator+=(const vecteur& v)

{
this-> x += v.x;
this-> y += v.y;
return *this;
}


vecteur& vecteur ::operator-=(const vecteur& v)

{
this->x -= v.x;
this->y -= v.y;
return *this;
}

Vous trouvez que c bien écrit ou bien dois-je utiliser "void"??

Je vous remercie d'avance de votre aide!

11 réponses

mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
8 janv. 2010 à 17:30
- Quelqu'un pourrait me définir le "lstinline"??

Ca n'a pas de signification en maths ni en C++ a priori. Ou ce n'est pas une terminologie classique.

- J'ai commencé à définir les opérateurs dans le header Vecteur2D.h comme suit:

En général on met une extension .hh, .hx ou .hpp au headers C++. Ça permet de distinguer les headers C++ des headers C (.h). De la même façon on note un fichier source C++ .cc, .cxx, .cpp. Personnellement j'utilise les notations .cpp et .hpp.

Au niveau du .cc c'est ok. En particulier, tu as pris le soin de bien mettre les const et les & comme il faut.

Il ne faut pas utiliser "void" à tort et à travers. Le mot clé void est utilisé devant le nom d'une fonction (non constructeur, non destructeur) si celle-ci ne retourne rien. Ce n'est le cas d'aucun des opérateurs que tu cherches à définir. Il faut vraiment retourner le *this modifié, c'est ce qui permettra d'écrire par exemple dans ton code :

vecteur v1(2,3), v2(0,5), v3(4,6);
vecteur v4 = v1 + v2 + v3;


En effet, tu évalues v1 + v2 (donc tu exploites le résultat retournée par l'addition), auquel tu ajoutes v3. Si + ne retourne pas de vecteur, impossible de chaîner une addition. C'est le même principe avec les autres opérateurs, typiquement <<.

Sur un opérateur += -= etc... ça peut paraître plus contestable, mais on peut imaginer que tu veuilles simultanément incrémenter/décrémenter une variable et tester le résultat. Le fait de retourner *this dans += permet d'écrire par exemple (en supposant que tu aies implémenté == pour la classe vecteur) :

if((v1 += v2) == vecteur(1,5)){
  //...
}


Au niveau du .hh, attention la méthode conj n'est pas implémentée, ce qui engendrera une erreur de compilation. Tu peux mettre dans ton .cc un squelette vide avec un commentaire TODO pour te souvenir de l'implémenter.

vecteur conj() const{
  // TODO
  std::cerr << "vecteur: conj: not yet implemented" << std::endl;
  return vecteur(0,0);
}


Vu que les fonctions sont très courtes dans ton .cc, on peut imaginer d'utiliser le mot clé "inline" du C++.

Bonne chance
0
hbelaid Messages postés 15 Date d'inscription lundi 27 avril 2009 Statut Membre Dernière intervention 30 janvier 2011
9 janv. 2010 à 16:56
Ah merci beaucoup!
ça me rassure de n'avoir pas tt faux!

Mais j'ai encore besoin de ton aide :S

Pour la mutiplication par un scalaire j'ai écrit ceci:
vecteur& operator*=(const double& alpha )

ça vous semble correct??
0
hbelaid Messages postés 15 Date d'inscription lundi 27 avril 2009 Statut Membre Dernière intervention 30 janvier 2011
9 janv. 2010 à 17:19
Je suis désolée je sais que je pose trop de questions
mais c vraiment important

dans un corrigé d'un autre TP, mon prof a écrit:

vecteur operator+(const vecteur& x , const vecteur& y )
{
vecteur res=x ;
res+=y ;
return res ;
}
vecteur operator-(const vecteur& x , const vecteur y )
{
vecteur res=x ;
res-=y ;
return res ;
}

Quelle écriture convient le mieux, la 1ère ou celle ci?

Merci encore
0
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
10 janv. 2010 à 03:09
Les deux sont bonnes et ne font pas la même chose. Dans un cas tu implémentes l'opérateur += et *=, dans l'autre les opérateurs + et *. En fait, en général :

x += a; // appel à +=


n'équivaut pas forcément à :

x = x + a; // appel à +


... même si c'est le cas en général.

Voici comment s'en convaincre :

#include <iostream>

class A{
    protected:
        int x;

    public:

        A(int x0 = 0):
            x(x0)
        {}

        A(const A & a0):
            x(a0.get_x())
        {}


        inline int get_x() const {
            return x;
        }

        inline void set_x(int x0){
            x = x0;
        }

};

inline A & operator += (A & a1,int x){
    std::cout << "Je passe par +=" << std::endl;
    a1.set_x(a1.get_x() + x);
    return a1;
}

inline A operator +(const A & a,int x0){
    std::cout << "Je passe par +" << std::endl;
    return A(a.get_x() + (10 * x0));
}

inline std::ostream & operator << (std::ostream & out,const A & a){
    out << a.get_x();
    return out;
}

int main(){
    A a1(6),a2(9);
    std::cout << "a1 = " << a1 << " a2 = " << a2 << std::endl;
    a1 += 4;
    std::cout << "a1 = " << a1 << " a2 = " << a2 << std::endl;
    a2 = a2 + 8;
    std::cout << "a1 = " << a1 << " a2 = " << a2 << std::endl;
    return 0;
}


Maintenant compilons et exécutons tout ça :

a1 = 6 a2 = 9
Je passe par +=
a1 = 10 a2 = 9
Je passe par +
a1 = 10 a2 = 89


On voit bien que les opérateurs sont bien distincts :
- en appelant +=, on n'a pas appelé + (sinon il y aurait écrit successivement "Je passe par +=" et "Je passe par +"),
- les valeurs finales de a1 et a2 le montrent également

Tu noteras que les opérateurs peuvent être codés en dehors ou à l'intérieur de la classe. Typiquement toi tu les as déclaré dans la classe (et tu aurais pu les implémenter dans la classe : dans ce cas ne pas oublier le mot clé inline).
https://forums.commentcamarche.net/forum/affich-37604414-les-inlines-en-c

La contrainte, quand tu les écris/déclare dans la classe, c'est que l'opérande de gauche à le type de la classe. Pour un opérateur comme << qui prend en membre de gauche un flux (par exemple std::cout) tu vois tout de suite le problème. Si l'opérande de gauche est de type A, les deux écritures ont leurs avantages, il n'y en a pas spécialement de meilleure.

- Quand tu écris l'opérateur binaire (avec deux opérandes) dans la classe, l'opérande de gauche a le type de la classe. Tu as également aux membres de la classe.

- Quand tu écris l'opérateur hors de la classe, tu peux potentiellement manipuler des opérandes de n'importe quel type. En tant que fonction implémentée hors de la classe, tu n'auras pas accès aux membres protégés ou privés (ce qui force à passer par des accesseurs, ce qui n'est pas forcément plus mal).

Bonne chance
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
hbelaid Messages postés 15 Date d'inscription lundi 27 avril 2009 Statut Membre Dernière intervention 30 janvier 2011
10 janv. 2010 à 12:36
Merci bcp!
0
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
10 janv. 2010 à 14:33
De rien !

Petite précision, la STL (standard template library) met à disposition des vecteurs n-aires templates. La code que tu classes à donc un rôle "scolaire" mais en pratique, on réutiliserait des std::vector, éventuellement via un héritage et en spécifiants quelques opérateurs spécifiques.
https://forums.commentcamarche.net/forum/affich-37604421-introduction-a-la-stl-en-c-standard-template-library

Bonne continuation
0
hbelaid Messages postés 15 Date d'inscription lundi 27 avril 2009 Statut Membre Dernière intervention 30 janvier 2011
10 janv. 2010 à 16:40
Bon pour la continuation... On nous demande autre chose aussi...
Je suis vraiment désolée d'abuser de ton temps mais comme tu as l'air de bien maîtriser C++, je voudrais te demander un autre coup de main

A présent je dois réaliser une classe de pts affines:
"On ne peut pas ajouter deux points affines ensemble et on ne peut pas multiplier un point affine par
un scalaire. Par contre, en soustrayant un point affine  à un autre on obtient un vecteur
e.g. B − A = AB(vecteur) . Et si on ajoute un vecteur à un point affine, on obtient un autre point affine.
Définir les opérations suivantes : addition d'un point et d'un vecteur (dans les deux sens), soustraction
d'un vecteur à un point et soustraction de deux points."

Pourrais tu me donner des indications pr l'écriture de la première opération pour que je puisse démarrer

Merci d'avance (je sais que je demande trop :(()
0
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
11 janv. 2010 à 00:31
Comme c'est un autre problème, ouvre un nouveau fil de discussion et on verra ;-)
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
11 janv. 2010 à 09:13
C'est pourtant évidant, on te demande que l'opération "-" prenne deux point et retourne un vecteur.
Il suffit alors de l'écrire :
vecteur operator-(point a,point b)
Note aussi qu'on peut voir tout point du repère comme un vecteur avec l'origine du repère. (notation couremment utiliser en physique avec le vecteur position.)
0
hbelaid Messages postés 15 Date d'inscription lundi 27 avril 2009 Statut Membre Dernière intervention 30 janvier 2011
11 janv. 2010 à 15:56
Je sais que c'est surement évident
Mais j'ai vraiment quelques notions élémentaires et j'ai du mal avec l'écriture en C++

En tout cas merci beaucoup
0
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
11 janv. 2010 à 23:07
Ouais d'ailleurs ça manque d'élégance ta réplique mon cher Char Sniper... Quand quelqu'un débute en C++ c'est normal qu'il pose des questions dont les réponses peuvent paraître évidentes... On est tous passés par là.
0