See site in english Voir le site en francais
Website skin:
home  download  forum  link  contact

Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

Author Topic: [tutorial] Scope des variables C++  (Read 2933 times)

0 Members and 1 Guest are viewing this topic.

Offline DanSteph

  • Administrator
  • Legend
  • *****
  • Posts: 15002
  • Karma: 178
  • Hein, quoi !?
    • FsPassengers
02 July 2007, 12:57:40

Cliquez le lien ci-dessous pour retourner au sommaire des "tutorials pour créer une DLL Orbiter"
http://orbiter.dansteph.com/forum/index.php?topic=6335.msg95352#msg95352



Scope des variables C++

"Scope" veut dire "portée" ou "visibilité". En C++ les variables peuvent être globale, locale
etc etc. Je vous fait un petit topo pour débroussailler ca.


NOTE: C'est quoi une variable?

Une variable contient une valeur. En C++ nous somme obligé de les déclarer avant utilisation
et de plus de les déclarer avec le type de données qu'elle va contenir. Une variable "int"
par exemple (integer ou entiere) ne pourra contenir que des valeurs entiere donc sans virgule
une variable "float" (virgule flottante) elle peut contenir des variable avec des "chiffres après
la virgule" exemple 10.965

Suivant ou la declaration ce fait cette variable aura un "scope" d'utilisation, elle ne pourra être
utilisée et ne sera visible que dans une certaine partie du code.

En C++ on peut declarer une variable et lui assigner directement une valeur dans la declaration,
ceci est une bonne manière de faire ca évite d'avoir des variable indéfinies qui auront une valeur
aléatoire:

Code: [Select]
   int Variable=0;                  // declaration ET initialisation
    Variable=Variable+10;  
    // ici variable =10 (0+10)

    int SecondVariable;
    SecondVariable=SecondVariable+10;
    // ici SecondVariablepeut etre n'importe quoi car (???+10) = ??? ( donc 124332453 par exemple)
Dans le second cas toutefois le compilateur va ce plaindre qu'une variable non initialisée est utilisée.


NOTE: Les noms de variable

Par convention la majeur partie des programmeurs utilisent une regle de nommage pour les variables
ca facilite la lecture du code d'abord et assure qu'un autre programmeur comprendra le code facilement.
Cette notation ce compose de la premiere lettre du type (float int double) suivis de nom explicite
qui commencent par une majuscule.

Code: [Select]
// JUSTE:
int iPositionAnimationCockpit;
float fOxygeneDansReservoireA;

// FAUX:
int B6453;                  // vous ne saurez plus a quoi elle sert dans un mois
float AnimationCockpit;   // 1000 lignes plus bas c'est quel type Animationcockpit ? float double int ?
int int                           // "int" est un mot clé reservé du C++


Scope des variables C++


Et pourquoi elle ne sont pas visible de partout ?

C'est vrai ca pourquoi elle seraient pas simplement globale visible de partout hein ? :rant:

Vous imaginez les prog avec quelques centaines de milliers de lignes et des milliers de variables globales
pour ne pas ce mélanger les pinceaux ? La centieme fois qu'on a *encore* besoin d'une variable relative à
l'altitude pour faire un calcul on l'appelle comment ? altitude_100 ? altitude_robert ? Bonjour le mix infernal
et la rigueur de moine dans les noms de variables pour éviter les bugs. Quand on ecrit quelques milliers
de lignes un telle rigueur est impossible à atteindre.

Que demande t'on a une fonction ? de nous pourrir la vie en nous rajoutant des dizaines de variables qu'on n'a besoin nulle part ailleurs ou faire un certain calcul et de nous renvoyer le(s) résultat simplement ?

En bref voyez les fonctions comme des usines: on leurs demande un certain boulot et on veut le résultat, ce qu'il s'y passe dedans on ne veut pas le savoir. A haut niveau votre programme est super clean, il ce borne à traiter les variables indispensable et à appeller des fonctions pour les traiter.

Une usine qui nous retourne un résultat, seule chose que nous voulons:
Code: [Select]
float GetResultat(float MonAltitude)
{
   float PI=3.14;
   MonAltitude+=1234;
   float Tangente=tan(13.34)*PI*MonAltitude;
   float MonCos=Tangente*MonAltitude*PI+Tangente;
   float MonResultat=MonAltitude+(PI*Tangente)/MonCos;
   return MonResultat;
}
Nous on ce borne à demander à notre usine notre résultat, ce qui ce passe dedans et les variables utilisée on s'en gratte le coquillard.

float LeResultat=GetResultat(4000);  // Au boulot !
MonCos=10.0; // Erreur compilation cette variable n'existe pas en dehors de la fonction GetResultat()


Variables locale:

Une variable locale est déclarée dans une fonction ou dans une instruction avec {}
et ne sera donc visible que dans cette partie entre les {}

Code: [Select]
void MaFonction(void)
{
     int VariableLocale;   // declaration    
     VariableLocale=10;  // utilisation OK car dans le même "scope" (entre {})
}
VariableLocale=10;   // erreur variable inconnue ici

Notez que cette variable est détruite à la fin de la fonction et recréée au début de la fonction
elle ne retiendra absolument pas sa valeurs.
Il existe un moyen de déclarer des variables locale qui retiennent leurs valeurs avec le mot
clé static devant mais c'est une mauvais manière de coder.

Nous pouvons avoir aussi des variables locale à une partie du code, même principe: variable
déclarée entre "{}" ne sera valide que entre ces "{}"

Code: [Select]
int Condition1=10;
int Condition2=10;
if(Condition1==Condition2)
{
     int VariableLocale;   // declaration    
     VariableLocale=Condition1;  // utilisation OK car dans le même "scope" (entre {})
     Condition1=0;  // Variable visible aussi ici car déclarée avant le bloc {}
}
VariableLocale=10;   // erreur variable inconnue ici

Et de même pour des boucles for next:

Code: [Select]
for(I=0;I{
     int VariableLocale;   // declaration    
     VariableLocale=I;  // utilisation OK car dans le même "scope" (entre {})
}
VariableLocale=10;   // erreur variable inconnue ici

Le parametre passé à une fonction est une variable déclarée implicitement dans cette fonction:
Code: [Select]
void MaFonction(int iPositionCockpit)
{
     iPositionCockpit=10;  // utilisation OK car dans le même "scope" (entre {})
}
iPositionCockpit=10;   // erreur variable inconnue ici


Une variable dois toujours etre déclarée AVANT d'etre utilisé, le C++ ce lit de haut en bas et de gauche à droite
en sequence. Ceci en dessous comme les autres erreurs plus haut refusera absolument de compiler.
Code: [Select]
iPositionCockpit=10;  // ERREUR cette variable n'existe pas encore à cette ligne
int iPositionCockpit;   // trop tard

Variables globale dans un source:

Une variable déclarée au début d'un source CPP sera visible de tout le code de ce CPP y compris fonctions etc etc.
Comme d'habitude le code ce lit de haut en bas.

Dans TITI.CPP
Code: [Select]
void MaFonctionA(void)
{
     iPositionCockpit=10;   // erreur variable encore inconnue ici
}

int iPositionCockpit=0;   // declaration de la variable ici

void MaFonctionB(void)
{
     iPositionCockpit=10;    // OK elle est déclarée plus haut
}
void MaFonctionC(void)
{
     iPositionCockpit=iPositionCockpit+10;    // OK elle est déclarée plus haut
}

Une telle variable n'est jamais detruite car elle est globale (en dehors d'une fonction ou d'un bloc {})
elle retient donc sa valeur durant toute la durée du programme

Si vous appelez 1x MaFonctionB() et 2x MaFonctionC() la variable iPositionCockpit aura la valeur 30
car si vous executez le code dans votre tete comme l'ordinateur le ferais:

iPositionCockpit=10;
iPositionCockpit=iPositionCockpit+10;
iPositionCockpit=iPositionCockpit+10;

iPositionCockpit = 30


Variables globale de classe:

Cas le plus fréquent d'orbiter.
Une variable globale de classe ce declare dans le header de la classe, s'initialise dans le constructeur (ou premiere fonction d'initialisation qui est executée) est valide dans toutes les fonctions membre de la classe et retient ca valeur.

Dans "MaDeclarationClass.h"
Code: [Select]
class MonAddon: VESSEL2
{
   // declaration des variables globale (membre) de cette classe
   int VariableA;
   int VariableB;

   //declaration des fonctions membre de cette classe
   void MaFonctionInitialisation(void);   // clbkSetClassCap() dans Orbiter
   void AutreFonctionA(void);
   void AutreFonctionB(void);
}

Je ne vais pas vous emm.. avec les constructeurs et les destructeurs on rentrerais dans le C++ complexe il suffit de savoir que constructeur ou fonction d'initialisation c'est la même chose: on doit absolument y initialiser ses variables avec une valeur par defaut car après déclaration dans votre classe elle ont une valeur indefinie. Dans Orbiter c'est la fonction clbkSetClassCap(); qui remplis cette fonction.

"l'implementation" de vos fonctions (le code proprement dis) ce fait dans un ou plusieurs fichier CPP ou le header est déclaré au début avec un "#include" (#include "MaDeclarationClass.h" dans notre exemple) On reconnait qu'il sont membres de cette classe par le mot clé "NomClasse::" devant le nom de fonction:

Dans "MonImplementation.cpp"
Code: [Select]
#include "MaDeclarationClass.h"

// fonction appellée une fois au début du programme, elle initialise par defaut nos valeurs. Dans orbiter
// ceci est fait par la fonction clbkSetClassCap() qui est appellée automatiquement par Orbiter.

void MonAddon::MaFonctionInitialisation(void)
{
   VariableA=0;         // intialisation
   VariableB=10;   //initialisation
}

void MonAddon::AutreFonctionA(void)
{
    VariableA=VariableA+VariableB;
}
void MonAddon::AutreFonctionB(void)
{
    VariableB=VariableB*VariableA;
}
}

Pouvez vous me dire maintenant quelle valeurs aurait VariableB après 1 appel a AutreFonctionA() et deux appel a AutreFonctionB() ? (on part du principe que la fonction d'initialisation a déjà été appellée au début du prog)

Facile: Au début du prog (après init) VariableA=0 et VariableB=10

on appelle 1x AutreFonctionA() donc "VariableA=VariableA+VariableB"
VariableA=0+10
VariableA=10 maintenant.

Ensuite on appelle 1x AutreFonctionB() donc "VariableB=VariableB*VariableA;"
Donc VariableB=10*10
VariableB=100 maintenant.

Ensuite on appelle 1x AutreFonctionB() donc "VariableB=VariableB*VariableA;"
Donc VariableB=100*10
VariableB=1000 maintenant.

Comprendo ? :badsmile:

Sinon posez vos questions ici:
http://orbiter.dansteph.com/forum/index.php?topic=6342.msg95437#msg95437

Dan



Message modifié ( 02-07-2007 16:58 )


Offline DanSteph

  • Administrator
  • Legend
  • *****
  • Posts: 15002
  • Karma: 178
  • Hein, quoi !?
    • FsPassengers
Reply #1 - 02 July 2007, 16:43:53

Cliquez le lien ci-dessous pour retourner au sommaire des "tutorials pour créer une DLL Orbiter"
http://orbiter.dansteph.com/forum/index.php?topic=6335.msg95352#msg95352




Message modifié ( 19-07-2007 13:43 )

« Last Edit: 02 July 2007, 16:43:53 by DanSteph »