Davantage d'opérateurs surchargés.

Deuxième exemple de surcharges d'opérateurs.

operator

Voir version :

Pas de dépendances

Télécharger :

#include <iostream>
#include <math.h>

class Vecteur
{
protected:
  double x,y,z;
public:
  Vecteur();
  Vecteur(const double& a,const double& b,const double& c);
  double& operator[] (int i);
  const double& operator[] (int i) const;
  Vecteur operator+();
  Vecteur operator-();
  Vecteur& operator+=(const Vecteur&);
  Vecteur& operator-=(const Vecteur&);
  Vecteur& operator*=(const Vecteur&);
  Vecteur& operator/=(const Vecteur&);
  Vecteur& operator*=(double);
  Vecteur& operator/=(double);
  friend Vecteur operator+(const Vecteur&, const Vecteur&);
  friend Vecteur operator-(const Vecteur&, const Vecteur&);
  friend double operator* (const Vecteur&, const Vecteur&);
  friend Vecteur operator* (const Vecteur&, double);
  friend Vecteur operator* (double, const Vecteur&);
  friend Vecteur operator/ (const Vecteur&, double);
  friend Vecteur operator/ (const Vecteur&, const Vecteur&);
  friend int operator==(const Vecteur&,const Vecteur&);
  friend int operator!=(const Vecteur&,const Vecteur&);
  friend int operator<(const Vecteur&,const Vecteur&);
  friend int operator>(const Vecteur&,const Vecteur&);
  friend Vecteur Orthogonal(const Vecteur&);
  friend double Norm(const Vecteur&);
  friend std::ostream& operator<<(std::ostream&,const Vecteur&);
};

using namespace std;

// IMPLEMENTATION


Vecteur::Vecteur()
{
    x=y=z=0.0;
}

Vecteur::Vecteur(const double& a,const double& b,const double& c)
{ 
    x=a; 
    y=b; 
    z=c;
}
  
double& Vecteur::operator[] (int i) 
{
    if (i == 0)
        return x;
    else if (i == 1) 
        return y;
    else
        return z;
}

const double& Vecteur::operator[] (int i) const
{
    if (i == 0)
        return x;
    else if (i == 1) 
        return y;
    else
        return z;
}

Vecteur Vecteur::operator+ ()
{
  return *this;
}

Vecteur Vecteur::operator- ()
{
  return Vecteur(-x,-y,-z);
}

Vecteur& Vecteur::operator+= (const Vecteur& u)
{
  x+=u.x; 
  y+=u.y; 
  z+=u.z;
  return *this;
}

Vecteur& Vecteur::operator-= (const Vecteur& u)
{
  x-=u.x; 
  y-=u.y; 
  z-=u.z;
  return *this;
}

Vecteur& Vecteur::operator*= (double a)
{
  x*=a; 
  y*=a; 
  z*=a;
  return *this;
}

Vecteur& Vecteur::operator/= (double a)
{
  x/=a; 
  y/=a; 
  z/=a;
  return *this;
}

Vecteur& Vecteur::operator*= (const Vecteur& u)
{
  x*=u.x; 
  y*=u.y; 
  z*=u.z;
  return *this;
}

Vecteur& Vecteur::operator/= (const Vecteur& u)
{
  x/=u.x; 
  y/=u.y; 
  z/=u.z;
  return *this;
}

Vecteur operator+ (const Vecteur& u, const Vecteur& v)
{
  return Vecteur(u.x+v.x,u.y+v.y,u.z+v.z);
}

Vecteur operator- (const Vecteur& u, const Vecteur& v)
{
  return Vecteur(u.x-v.x,u.y-v.y,u.z-v.z);
}

// Produit scalaire
double operator* (const Vecteur& u, const Vecteur& v)
{
  return (u.x*v.x+u.y*v.y+u.z*v.z);
}

Vecteur operator* (const Vecteur& u,double a)
{
  return Vecteur(u.x*a,u.y*a,u.z*a);
}

Vecteur operator* (double a, const Vecteur& v)
{
  return v*a;
}

// produit Vectoriel
Vecteur operator/ (const Vecteur& u, const Vecteur& v)
{
  return Vecteur(u.y*v.z-u.z*v.y,u.z*v.x-u.x*v.z,u.x*v.y-u.y*v.x);
}

Vecteur operator/ (const Vecteur& u, double a)
{
  return Vecteur(u.x/a,u.y/a,u.z/a);
}

int operator== (const Vecteur& u,const Vecteur& v)
{
  return ((u.x==v.x)&&(u.y==v.y)&&(u.z==v.z));
}

int operator!= (const Vecteur& u,const Vecteur& v)
{
  return (!(u==v));
}

double Norm(const Vecteur& u)
{
  return sqrt(u.x*u.x+u.y*u.y+u.z*u.z);
}

int operator<(const Vecteur& a,const Vecteur& b)
{
  return ((a.x<b.x)&&(a.y<b.y)&&(a.z<b.z));
}

int operator>(const Vecteur& a,const Vecteur& b)
{
  return ((a.x>b.x)&&(a.y>b.y)&&(a.z>b.z));
}

Vecteur Orthogonal(const Vecteur& u)
{  
  Vecteur a=Vecteur(fabs(u[0]),fabs(u[1]),fabs(u[2]));
  int i=0;
  int j=1;
  if (a[0]>a[1])
  {
    if (a[2]>a[1])
    {
      j=2;
    }
  }
  else
  {
    i=1;
    j=2;
    if (a[0]>a[2])
    {
      j=0;
    }
  }
  a=Vecteur(0.0,0.0,0.0);
  a[i]=u[j];
  a[j]=-u[i];
  return a;
}

std::ostream& operator<<(std::ostream& os,const Vecteur& v)
{
    return os << "(" << v.x << "," << v.y << "," << v.z << ")";
}

// PROGRAMME PRINCIPALE 

int main()
{
    Vecteur a(1,0,0);
    Vecteur b(0,1,0);
    Vecteur c=a/b;
    cout << "3e vecteur de base : " << c << endl;
    a+=b;
    a/=2.0;
    cout << "produit scalaire entre a " << a << " et b " << b << " = " << a*b << endl;
    cout << "norme de a = " << Norm(a) << endl;
    cout << "je rappelle la valeur du vecteur a : " << a << endl;
    cout << "un vecteur orthogonal au vecteur a : " << Orthogonal(a) << endl;
    system("Pause");
    return 0;
}






Commentaires

	Voici un long tutorial :

  Il illustre la puissance des surcharges de fonctions !
  Vous devez connaitre les vecteurs pour comprendre l'exemple. Au pire dites voir qu'un vecteur est une fleche
  que cette fleche a 3 coordonnées : x,y,z (oui, vecteur dans l'espace)
  Bref.
  (ce tutorial est difficile, mais si vous y arrivez, vous maitriserez les surcharges en tout genre)
  (si vous ne comprenez pas, rien ne vous empeche de passer au suivant, et de revenir ici plus tard)


  Pour le moment, ne regardez que le main.

  On déclare un vecteur a, de coordonnée 1,0,0
  (pour le moment, je rappelle, on ne regarde que le main, donc admettez que ça marche comme ça)
  
  On déclare un vecteur b, de coordonnées 0,1,0

  Ensuite, on déclare un vecteur c, qui est la division de a et de b.
  Diviser 2 vecteurs ????
  Les mathématiciens vont hurler ! On ne peut pas diviser 2 vecteurs !

  Et bien moi, je vous dis, que, dans mon cas, je dis que la division de 2 vecteurs, ça donne le produit vectoriel.
  (C'est moi qui aie décidé ça)

  Donc je dis que c est le vecteur produit vectoriel entre a et b.
  (si vous ne savez pas ce que c'est, dites vous que c'est une opération)

  Ensuite, j'affiche le vecteur, avec un simple cout. (ah bon ?? on savait que cout savait afficher des float, des int,
  mais des "Vecteur" il sait faire ça ??) faut croire puisque ça compile...

  J'ajoute b au vecteur a (l'addition de 2 vecteurs, c'est facile, c'est la relation de Chasles)
  Je divise le vecteur a par la constante 2.0 : toutes les coordonnées sont divisées par 2.

  j'affiche des vecteurs, j'affiche le produit scalaire (je dis que si on fait * entre 2 vecteurs, ça donne un double qui est 
  un produit scalaire...)
  J'affiche la norme du vecteur en mettant juste Norm(a)
  Et j'affiche un vecteur orthognal en mettant Orthogonal(a)

  Voila !!
  Conclusion :

  Je manipule des vecteurs tres simplement, comme si je manipulais des int !!!!
  D'ou vient ce prodige ? Pourtant, le C++ ne connait pas du tout la notion de vecteurs !!

  Comment fait il pour faire marcher tout ça aux petits oignons ?

  Réponse : la classe Vecteur, et les surcharges d'opérateurs divers !!

********************************

  Nous allons regarder les membres de Vecteur, un par un :

Vecteur();

  Le constructeur par défaut, regardez son implémentation : si on appelle la classe sansa parametre, il initialise au 
  vecteur nul.

Vecteur(const double& a,const double& b,const double& c);

  Le constructeur de base : on passe des double a,b,c, et les coordonnées des vecteurs sont remplies.
  Note: c'est lui qui est appelé lors de la construction de a et b.

  Pourquoi des appels par référence ? 
  Pour optimiser ! Je ne vous cacherai pas que cette classe a déja été utilisée dans plusieurs applications 3D, des petits
  jeux 3D, qui devaient aller vite. Le vecteur est tres souvent appelé (car tout ce qui est 3D demande des points et des 
  vecteurs, faut que ça carbure !)
  Un appel par référence, implicitement, c'est comme appeler par pointeurs :
  un pointeur, c'est 4 octets. Donc passer 4 pointeurs revient a passer 12 octets
  un double, si on avait passé des double directement, c'est 8 octets, ce qui aurait demandé de passer 3*8 = 24 octets
  si on avait fait par copie, ce qui aurait ralenti un petit peu (sans etre vraiment visible pour etre honnete, lol...)
  Si le const vous gene, dites vous simplement qu'il s'agit d'une sécurité :
  Ce const assure simplement celui qui appelle la fonction que ses a,b,c ne seront JAMAIS modifiés.
  En effet, si vous passez b par référence par exemple, peut etre que la fonction va le modifier. A vous de voir avec 
  celui qui a programmé la fonction... Mais si vous mettez const, il vous assure que ce ne sera pas modifié
  (ie : s'il met const et qu'il essaie, dans sa fonction, de faire b=0.0, il se fait correctement envoyer chier par le 
  compilateur)
  Le fait de mettre const vous permet également de pouvoir passer des constantes :
  bref, de toute façon, const gene pas mal de monde, mais est bien pratique je ferai un tuto dans les chapitres suivants sur const.

double& operator[] (int i);

  Ah ! celui la est intéressant.
  On surcharge l'opérateur [] : le but est, bien entendu, de renvoyer une composante d'un vecteur :

  par exemple, si vous avez le vecteur V (3,5,8);
  V[0] vaut 3;
  V[1] vaut 5;
  V[2] vaut 8;

  C'est pratique d'avoir cet opérateur (regardez comment il est implémenté)

  Vous pouvez donc écrire, en toute logique, 
  double t;
  t= V[0];

  pas de soucis.

  Maintenant, constatez que le double renvoyé est renvoyé par référence :
  Cela signifie qu'il s'agit d'une fonction dite de L-VALUE.
  L-Value signifie (Left Value), ça veut dire, littéralement, que vous pouvez la mettre a gauche du =.
  Vous pouvez donc écrire :

  V[0] = 2;

  --> Et vous modifiez V[0] directement ainsi !!
  Le fait, donc, de renvoyer une référence, permet de faire uen L-Value function, qui permet donc de pouvoir utiliser
  la meme fonction pour lire et écrire. Assez puissant n'est ce pas ?

const double& operator[] (int i) const;

  Compliqué pour le moment, on verra ça dans le tuto du const, ne vous embettez pas avec ça pour le moment.

Vecteur operator+();

  On passe aux opérateurs.
  Ici, regardons : pas d'arguments, on retourne un Vector :
  Cette signature est la signature du + unaire,
  c'est a dire que cet opérateur est appelé si vous faites quelque chose de la sorte :

  Vecteur V;
  Vecteur W;
  V = +W ;   // on appelle ça le + unaire. (de UN (1) opérande simplement)

  on constate que l'implémentation est juste un return *this.
  this est un pointeur sur l'instance courante. donc *this est l'instance courante.
  En gros, ça renvoie lui meme, c'est tout a fait logique, puisque V=+W, c'est la meme chose que V=W
  donc +W renvoie W...
  
  Vecteur operator-();

  Le - unaire : si on fait :
  V= -W

  Mathématiquement, cela revient a changer le signe de chaque composante. C'est ce que vous pouvez voir dans l'implémentation.

Vecteur& operator+=(const Vecteur&);

  La surcharge de l'opérateur += :

  si je fais 
  V+=W; ça revient au meme que V=V+W;
  mais donc ça modifie V. Du coup, cet opérateur prend V, ajoute les champs de W, et se retourne lui meme, comme le + unaire.

Vecteur& operator-=(const Vecteur&);

  Pareil que +=

Vecteur& operator*=(const Vecteur&);

  Pareil que +=  : ici, ça multiplie tous les membres par ceux de W

Vecteur& operator/=(const Vecteur&);

  Pareil, ça divise cette fois...

Vecteur& operator*=(double);

  ici, on va multiplier tous les membres du vecteur par une constante
  
Vecteur& operator/=(double);

  ici, on va les diviser.

friend Vecteur operator+(const Vecteur&, const Vecteur&);

  Ah ! cette fois, voici une fonction amie. Une telle fonction est comme une fonction normale : ça veut dire qu'elle 
  n'appartient pas a la classe.

  Quand vous faites :
  maclasse m;
  m.truc();

  alors vous appelez truc sur l'instance m;

  Quand vous faites :

  Vecteur V;
  V*=2.0;
  Alors c'est pareil que :

  V.operator*=(2.0);

  Vous travaillez sur l'instance de V.
  Implicitement, vous passez V devant.

  La fonction amie (déclarée avec friend) est hors de la classe :
  Ainsi :
  V.operator+(Vecteur(),Vecteur())  N'EXISTE PAS.

  ce qui existe, c'est :

  operator+(Vecteur(),Vecteur())
  Vous pouvez d'ailleurs constater dans son implémentation que l'on ne colle pas Vecteur:: devant.

  Mais alors, pourquoi la déclarer dans la classe, puisqu'elle lui est extérieure ?
  --> Parce qu'une fonction amie est une fonction privilégiée qui a le droit d'accéder aux champs privés de la classe :

  En effet, dans l'implémentation de 

	operator+(Vecteur(),Vecteur())
	vous pouvez constater qu'on accede a x, y et z. Ce qui serait refusé si la fonction n'était pas amie...
	Voila a quoi sert une fonction amie.
	
  Ici, cette fonction ajoute 2 vecteurs passés en parametres, et en renvoie un, tout naturellement.

friend Vecteur operator-(const Vecteur&, const Vecteur&);

  Meme chose pour soustraire 2 vecteurs.

friend double operator* (const Vecteur&, const Vecteur&);

  Le produit scalaire : retourne un double. Si vous ne savez pas ce que c'est, c'est une opération bien utile pour les vecteurs.
  La fonction prend donc 2 vecteurs, et retourne un double.

friend Vecteur operator* (const Vecteur&, double);

  Multiplier un vecteur par un double revient a multiplier chacune de ses composantes par le double.
  W = V*2.0;

friend Vecteur operator* (double, const Vecteur&);

  Ici, c'est la meme chose que ci dessus mais permet d'écrire :

  W = 2.0*V;

friend Vecteur operator/ (const Vecteur&, double);

  Ici, on divise un vecteur par un double (chaque composante)

friend Vecteur operator/ (const Vecteur&, const Vecteur&);

  Voici le produit vectoriel : je définis que la division entre 2 vecteurs redonne un vecteur, qui est le produit vectoriel

friend int operator==(const Vecteur&,const Vecteur&);

  Ici, je définis l'opérateur == :

  Ainsi je peux écrire :

  if (V==W)
  {
  ....
  }

  ça renvoie un int : ça doit renvoyer 1 si c'est égal, 0 sinon.

friend int operator!=(const Vecteur&,const Vecteur&);

  Exactement l'inverse.

friend int operator<(const Vecteur&,const Vecteur&);

  Assez bizarre comme opérateur : renvoie vrai si les 3 composantes du 1er sont plus petites que les 3 du 2eme

friend int operator>(const Vecteur&,const Vecteur&);

  Pareil, avec >

friend Vecteur Orthogonal(const Vecteur&);

  Une méthode sympa : donne un vecteur orthogonal a celui passé en parametres

friend double Norm(const Vecteur&);

  Donne la norme du vecteur.

friend std::ostream& operator<<(std::ostream&,const Vecteur&);

  Surcharge de l'opérateur << pour le cout !
  En effet, quand on fait des cout, comment savoir comment "ecire" le vecteur ?
  Cette surcharge permet de le faire.

  Note : j'ai mis les std:: devant, car le using namespace mis au dessus de ma classe faisait planter mon compilateur 
  (un des rares bugs de mon compilo, corrigé dans les versions d'apres)
  Essayez de mettre le using tout en haut, et d'enlever les std, de façon a avoir :

	friend ostream& operator<<(ostream&,const Vecteur&);

  Comprenez comment fonctionne la surcharge d'opérateur << : ostream désigne un flux de sortie.


  Voila, si vous arrivez au bout en ayant tout compris, c'est surement que vous avez déja fait du C++.
  Je développerai davantage cette partie en fonction des questions qui me seront posées.

*/

/* Note :

  Comme vous l'avez remarqué, la définition de la classe, son implémentation, et le main, sont dans le meme fichier.

  Si on veut faire propre, il faut faire 3 fichiers :

*********
Vecteur.h
*********

#ifndef _VECTEUR_H
#define _VECTEUR_H

#include <iostream>
#include <math.h>

using namespace std;

class Vecteur
{
protected:
  double x,y,z;
public:
  Vecteur();
  Vecteur(const double& a,const double& b,const double& c);
  double& operator[] (int i);
  const double& operator[] (int i) const;
  Vecteur operator+();
  Vecteur operator-();
  Vecteur& operator+=(const Vecteur&);
  Vecteur& operator-=(const Vecteur&);
  Vecteur& operator*=(const Vecteur&);
  Vecteur& operator/=(const Vecteur&);
  Vecteur& operator*=(double);
  Vecteur& operator/=(double);
  friend Vecteur operator+(const Vecteur&, const Vecteur&);
  friend Vecteur operator-(const Vecteur&, const Vecteur&);
  friend double operator* (const Vecteur&, const Vecteur&);
  friend Vecteur operator* (const Vecteur&, double);
  friend Vecteur operator* (double, const Vecteur&);
  friend Vecteur operator/ (const Vecteur&, double);
  friend Vecteur operator/ (const Vecteur&, const Vecteur&);
  friend int operator==(const Vecteur&,const Vecteur&);
  friend int operator!=(const Vecteur&,const Vecteur&);
  friend int operator<(const Vecteur&,const Vecteur&);
  friend int operator>(const Vecteur&,const Vecteur&);
  friend Vecteur Orthogonal(const Vecteur&);
  friend double Norm(const Vecteur&);
  friend std::ostream& operator<<(std::ostream&,const Vecteur&);
};

#endif

***********
Vecteur.cpp
***********

#include "vecteur.h"

Vecteur::Vecteur()
{
	x=y=z=0.0;
}

Vecteur::Vecteur(const double& a,const double& b,const double& c)
{ 
	x=a; 
	y=b; 
	z=c;
}
  
double& Vecteur::operator[] (int i) 
{
    if (i == 0)
		return x;
    else if (i == 1) 
		return y;
    else
		return z;
}

const double& Vecteur::operator[] (int i) const
{
    if (i == 0)
		return x;
    else if (i == 1) 
		return y;
    else
		return z;
}

Vecteur Vecteur::operator+ ()
{
  return *this;
}

Vecteur Vecteur::operator- ()
{
  return Vecteur(-x,-y,-z);
}

Vecteur& Vecteur::operator+= (const Vecteur& u)
{
  x+=u.x; 
  y+=u.y; 
  z+=u.z;
  return *this;
}

Vecteur& Vecteur::operator-= (const Vecteur& u)
{
  x-=u.x; 
  y-=u.y; 
  z-=u.z;
  return *this;
}

Vecteur& Vecteur::operator*= (double a)
{
  x*=a; 
  y*=a; 
  z*=a;
  return *this;
}

Vecteur& Vecteur::operator/= (double a)
{
  x/=a; 
  y/=a; 
  z/=a;
  return *this;
}

Vecteur& Vecteur::operator*= (const Vecteur& u)
{
  x*=u.x; 
  y*=u.y; 
  z*=u.z;
  return *this;
}

Vecteur& Vecteur::operator/= (const Vecteur& u)
{
  x/=u.x; 
  y/=u.y; 
  z/=u.z;
  return *this;
}

Vecteur operator+ (const Vecteur& u, const Vecteur& v)
{
  return Vecteur(u.x+v.x,u.y+v.y,u.z+v.z);
}

Vecteur operator- (const Vecteur& u, const Vecteur& v)
{
  return Vecteur(u.x-v.x,u.y-v.y,u.z-v.z);
}

// Produit scalaire
double operator* (const Vecteur& u, const Vecteur& v)
{
  return (u.x*v.x+u.y*v.y+u.z*v.z);
}

Vecteur operator* (const Vecteur& u,double a)
{
  return Vecteur(u.x*a,u.y*a,u.z*a);
}

Vecteur operator* (double a, const Vecteur& v)
{
  return v*a;
}

// produit Vectoriel
Vecteur operator/ (const Vecteur& u, const Vecteur& v)
{
  return Vecteur(u.y*v.z-u.z*v.y,u.z*v.x-u.x*v.z,u.x*v.y-u.y*v.x);
}

Vecteur operator/ (const Vecteur& u, double a)
{
  return Vecteur(u.x/a,u.y/a,u.z/a);
}

int operator== (const Vecteur& u,const Vecteur& v)
{
  return ((u.x==v.x)&&(u.y==v.y)&&(u.z==v.z));
}

int operator!= (const Vecteur& u,const Vecteur& v)
{
  return (!(u==v));
}

double Norm(const Vecteur& u)
{
  return sqrt(u.x*u.x+u.y*u.y+u.z*u.z);
}

int operator<(const Vecteur& a,const Vecteur& b)
{
  return ((a.x<b.x)&&(a.y<b.y)&&(a.z<b.z));
}

int operator>(const Vecteur& a,const Vecteur& b)
{
  return ((a.x>b.x)&&(a.y>b.y)&&(a.z>b.z));
}

Vecteur Orthogonal(const Vecteur& u)
{  
  Vecteur a=Vecteur(fabs(u[0]),fabs(u[1]),fabs(u[2]));
  int i=0;
  int j=1;
  if (a[0]>a[1])
  {
    if (a[2]>a[1])
    {
      j=2;
    }
  }
  else
  {
    i=1;
    j=2;
    if (a[0]>a[2])
    {
      j=0;
    }
  }
  a=Vecteur(0.0,0.0,0.0);
  a[i]=u[j];
  a[j]=-u[i];
  return a;
}

std::ostream& operator<<(std::ostream& os,const Vecteur& v)
{
	return os << "(" << v.x << "," << v.y << "," << v.z << ")";
}



*******************
Cequevousvoulez.cpp
*******************

#include "vecteur.h"

int main()
{
	Vecteur a(1,0,0);
	Vecteur b(0,1,0);
	Vecteur c=a/b;
	cout << "3e vecteur de base : " << c << endl;
	a+=b;
	a/=2.0;
	cout << "produit scalaire entre a " << a << " et b " << b << " = " << a*b << endl;
	cout << "norme de a = " << Norm(a) << endl;
	cout << "je rappelle la valeur du vecteur a : " << a << endl;
	cout << "un vecteur orthogonal au vecteur a : " << Orthogonal(a) << endl;
	system("Pause");
	return 0;
}

*********************************

Voila !

Ainsi, vous avez une classe indépendante : vous pouvez l'inclure ou vous voulez.

Question : pourquoi :

#ifndef _VECTEUR_H
#define _VECTEUR_H

#endif

-->
Parce que, si vous avez un projet, un gros projet de plusieurs fichiers, ou plusieurs fichiers ont besoin de manipuler
des vecteurs, alors vous aurez plusieurs fichiers qui inclueront vecteur.h
Si vous ne mettez pas de #ifndef, alors le compilateur essaiera de compiler plusieurs fois vecteur dans votre projet,
ce qui est ridicule, et surtout qui ne marchera pas.
En mettant ces 3 lignes, vous dites :

si _VECTEUR_H  n'est pas défini
alors vous le définissez, et vous procédez a la compilation de la classe.

Comme ça, la premiere fois qu'il passe, ce n'est pas défini, il compile vecteur,
les fois d'apres, c'est défini, il n'y recompile pas.

A la sortie, il n'y aura compilé qu'une seule fois : ce qu'on voulait...

Si vous faites des fichiers .h, il est donc ultra conseillé d'utiliser cela.
Il est d'usage d'appeler la constante de définition :

_NOMDEFICHIER_H