This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
in204:cpp:syntax:class [2019/09/16 13:11] 147.250.35.104 [Les sections internes d'une classe] |
in204:cpp:syntax:class [2022/11/18 10:50] (current) |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Introduction à la déclaration des classes ====== | + | ====== Les classes en C++ ====== |
+ | |||
+ | ===== La déclaration d'une classe ===== | ||
Une classe définissant un objet est défini comme une [[in204:cpp:syntax:struct|structure]] contenant en plus des champs de la structure des fonctions membres. | Une classe définissant un objet est défini comme une [[in204:cpp:syntax:struct|structure]] contenant en plus des champs de la structure des fonctions membres. | ||
Line 16: | Line 18: | ||
</code> | </code> | ||
- | ===== Définition des fonctions membres ===== | ||
- | La définition de la fonction peut contenir soit l'entête de la fonction membre suivi de son code : | + | ===== Les membres d'une classe ===== |
- | <code cpp> | + | Les éléments membres d'une classe peuvent être : |
- | #include <cmath> | + | * des champs à l'instar des ''struct'' en C. Ces champs ont un type qui peut-être soit un type simple, soit un type structuré, tableau ou objet. Ces définitions de champs définissent les valeurs internes à l'objet. |
+ | * des [[in204:cpp:syntax:class::functions|fonctions membres]], il s'agit de fonctions qui peuvent accédées et modifiées les valeurs internes de l'objet. Elles peuvent aussi appelées d'autres fonctions internes à l'objet. | ||
+ | * des [[in204:cpp:syntax:class::constructor|constructeurs]] qui sont des fonctions membres particulières qui initialisent l'objet au moment de la création de l'objet. | ||
+ | * d'un [[in204:cpp:syntax:class::destructor|destructeur]] qui est une fonction membre particulière qui est appleé au moment de la destruction de l'objet. | ||
+ | * des [[in204:cpp:syntax:class:type|définitions de types]]. Ces définitions de type sont propres à l'objet. | ||
+ | * des définitions de fonctions membres et de champs statiques qui sont partagées par tous les objets étant instance de la même classe. | ||
- | struct Vector | + | ===== Accès aux éléments d'un objet ===== |
- | { | + | |
- | double x; | + | |
- | double y; | + | |
- | double norm() | + | Nous faisons la distinction entre les éléments qui sont propres à un objet instance d'une classe. Ces éléments sont : |
- | { | + | |
- | return sqrt(x*x + y*y); | + | |
- | } | + | |
- | } | + | |
- | </code> | + | * les champs de l'objet, |
+ | * les fonctions membres de l'objet, | ||
- | soit nous pouvons scinder la déclaration de la fonction membre en définissant au sein de la classe le prototype de la fonction membre. Le code de la fonction membre sera défini en dehors de la classe. | + | A l'exception |
+ | * des champs et fonctions membres dites [[in204:cpp:syntax:class:static|statiques]]. | ||
+ | * des constructeurs et des destructeurs d'un objet qui normalement ne sont pas directement invoquées mais indirectement au moment de la construction ou de la destruction d'un objet et selon une syntaxe particulière. | ||
- | <code cpp> | + | Et les autres composantes de l'objet qui sont communes à tous les instances d'une classes que sont : |
- | #include <cmath> | + | * les champs et fonctions membres dites statiques, |
+ | * les définitions des types ou des alias de type, | ||
- | struct Vector | ||
- | { | ||
- | double x; | ||
- | double y; | ||
- | double norm(); | ||
- | } | ||
- | double Vector::norm() | + | ==== Accès aux fonctions membres et aux champs propres à l'objet instance d'une classe ===== |
- | { | + | |
- | return sqrt(x*x + y*y); | + | |
- | } | + | |
- | </code> | + | Pour pouvoir accéder aux champs et aux fonctions membres d'un objet à l'exception des champs et membres statiques de l'objet, nous utilisons : |
- | + | ||
- | + | ||
- | Dans ce cas, il est possible de mettre la définition du code de la fonction dans un fichier ''".h"'' ou ''".hpp"'' | + | |
- | + | ||
- | <code cpp> | + | |
- | // Fichier Vector.hpp | + | |
- | #ifndef VectorHPP | + | |
- | #define VectorHPP | + | |
- | + | ||
- | #include <cmath> | + | |
- | + | ||
- | struct Vector | + | |
- | { | + | |
- | double x; | + | |
- | double y; | + | |
- | + | ||
- | double norm(); | + | |
- | }; | + | |
- | #endif | + | |
- | </code> | + | |
- | + | ||
- | et le code de la fonction membre dans le fichier ''".cc"'' ou ''".cpp"'': | + | |
- | + | ||
- | <code cpp> | + | |
- | // Fichier Vector.cpp | + | |
- | + | ||
- | #include "Vector.hpp" | + | |
- | + | ||
- | double Vector::norm() | + | |
- | { | + | |
- | return sqrt(x*x + y*y); | + | |
- | } | + | |
- | + | ||
- | </code> | + | |
- | + | ||
- | ===== Accéder aux champs et fonctions membres d'un objet ===== | + | |
- | + | ||
- | Pour accéder aux champs et aux fonctions d'un objet, nous utilisons : | + | |
* soit l'opérateur ''.'', | * soit l'opérateur ''.'', | ||
Line 128: | Line 84: | ||
</code> | </code> | ||
+ | ==== Accès aux autres éléments définis dans la classe ===== | ||
+ | Pour accéder aux définitions de types présentes dans l'objets, nous référençons ces éléments en préfixant le nom de l'élément référencé par le nom de la classe suivit de ''::''. | ||
+ | |||
+ | Ainsi si nous considérons la classe des nombres complexes : | ||
+ | |||
+ | <code cpp> | ||
+ | class Complex | ||
+ | { | ||
+ | public: | ||
+ | |||
+ | class Polar {}; // Classe vide ne servant qu'à définir un | ||
+ | // type additionnel pour identifier | ||
+ | // une conversion polaire vers complexe. | ||
+ | private: | ||
+ | double re; | ||
+ | double im; | ||
+ | |||
+ | public: | ||
+ | Complex(): re(0.0), im(0.0) // Constructeur par défaut. | ||
+ | {} | ||
+ | Complex(const Complex& theSource): // Constructeur de recopie | ||
+ | re(theSource.re), im(theSource.im) | ||
+ | {} | ||
+ | Complex(double aFloat): // Conversion | ||
+ | re(aFloat), im(0.0) | ||
+ | {} | ||
+ | Complex(double theReal, double theImaginary) | ||
+ | re(theReal), im(theImaginary) // Constructeur spécialisé | ||
+ | {} | ||
+ | Complex(Polar, double theRho, double thePhi) | ||
+ | re(theRho* cos(thePhi)), im(theRho* sin(thePhi)) | ||
+ | {} | ||
+ | }; | ||
+ | </code> | ||
+ | |||
+ | Il est possible d'accéder à la classe ''Polar'' de ''Complex'' en préfixant ''Polar'' par ''Complex::Polar''. Ainsi l'appel : | ||
+ | <code cpp> | ||
+ | Complex::Polar polar; | ||
+ | Complex complexNumber(polar, 2.0, 0,52); | ||
+ | </code> | ||
+ | est parfaitement valide, même si habituellement, nous écrirons plutôt : | ||
+ | <code cpp> | ||
+ | Complex complexNumber(Complex::Polar(), 2.0, 0,52); | ||
+ | </code> | ||
+ | et nous nous affranchirons ainsi de la valeur intermédiaire ''polar''. | ||
+ | |||
+ | |||
+ | ==== Sections ''private'', ''protected'' et ''public'' ===== | ||
+ | |||
+ | Les mots clés ''private'', ''protected'' et ''public'' modifient la visibilité des différents éléments dans une classe. Pour plus d'informations, le chapitre détaille les différents niveaux [[in204:cpp:syntax:public|d'accessibilité aux champs et membres]] notamment dans le cadre de l'héritage. | ||
+ | |||
+ | * Un élément d'une classe est dit ''public'' s'il est accessible à la fois par les fonctions membres de la classe mais aussi par les autres fonctions (fonctions du programme ou fonctions membres d'une autre classe). | ||
+ | |||
+ | * Un élément d'une classe est dit ''private'' s'il est accessible par les fonctions membres de la classe mais aussi par n'est pas visible par les autres fonctions (fonctions du programme ou fonctions membres d'une autre classe). | ||
+ | |||
+ | <code cpp> | ||
+ | class Point | ||
+ | { | ||
+ | private: | ||
+ | double x; // les champs x et y sont déclarées privées | ||
+ | double y; // ils ne pourront qu'être accédés par les méthodes | ||
+ | // internes de la classe. | ||
+ | public: | ||
+ | int getX() { return x; } // accède au champ x. | ||
+ | int getY() { return y; } // accède au champ y. | ||
+ | |||
+ | } | ||
+ | </code> | ||
+ | |||
+ | En conséquence : | ||
+ | |||
+ | <code cpp> | ||
+ | |||
+ | int main() | ||
+ | { | ||
+ | Point p; | ||
+ | | ||
+ | std::cout << "L'abcisse de p est " << p.getX() << std::endl; | ||
+ | // L'accès à la méthode p est possible parce que la fonction membre | ||
+ | // getX est publique. | ||
+ | | ||
+ | std::cout << "L'abcisse de p est " << p.x << std::endl; | ||
+ | // L'accès au champ p est impossible parce que le champ | ||
+ | // p n'est pas public. | ||
+ | } | ||
+ | | ||
+ | </code> | ||
+ | |||
+ | ===== Fonction membres ''const'' & objets modifiables ===== | ||
+ | |||
+ | La classe ''Point'' précédemment définie introduit deux fonctions membres qui ne font que lire le contenu des champs ''x'' et ''y'' de l'objet. Ces méthodes ne modifiant par l'objet, il peut-être ajouter le qualificateur [[in204:cpp:syntax:const|''const'']] à ces deux méthodes. | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | class Point | ||
+ | { | ||
+ | private: | ||
+ | double x; // les champs x et y sont déclarées privées | ||
+ | double y; // ils ne pourront qu'être accédés par les méthodes | ||
+ | // internes de la classe. | ||
+ | public: | ||
+ | int getX() const { return x; } // accède au champ x. Cette méthode ne modifie | ||
+ | // pas l'objet | ||
+ | int getY() const { return y; } // accède au champ y.Cette méthode ne modifie | ||
+ | // pas l'objet | ||
+ | |||
+ | } | ||
+ | </code> | ||
+ | |||
+ | Mettre le qualification ''const'' à une méthode signifie que cette méthode ne peut pas modifier l'objet. Ceci a pour conséquence : | ||
+ | * de n'accéder aux champs de l'objet qu'en lecture uniquement. La méthode ne peut pas affectée une nouvelle valeur à un champ. | ||
+ | * de ne pouvoir qu'appeler des méthodes qui ont le qualificateur ''const'', ie. qui garantissent ne pas modifier l'objet. | ||
+ | |||
+ | Ainsi le code suivant génère une erreur à la compilation : | ||
+ | |||
+ | <code cpp> | ||
+ | struct Vector | ||
+ | { | ||
+ | ... | ||
+ | double getX() const { return X; } | ||
+ | double getY() const {return Y; } | ||
+ | void setX(double aValue) const { X = aValue; } | ||
+ | // Erreur de compilation, ne peut pas modifier x. | ||
+ | void setY(double aValue) { Y = aValue; } | ||
+ | |||
+ | void norm() const { return sqrt(X*X + Y*Y); } | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | De même, il n'est pas possible d'appeler une méthode qui n'est pas marquée ''const'' si l'objet a été déclaré ''const''. | ||
+ | |||
+ | <code cpp> | ||
+ | |||
+ | int main() | ||
+ | { | ||
+ | const Vector& vector = Vector(); | ||
+ | vector.setX(3.0); // Erreur de compilation, vector n'est pas modifiable. | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | ===== Le pointeur this ====== | ||
+ | |||
+ | Dans une fonction membre, le mot clé ''this'' désigne le pointeur faisant référence à l'instance de l'objet qui est à l'origine de l'appel de la méthode. | ||
+ | |||
+ | Disposer de la référence sur l'objet dans la méthode est principalement pour les usages suivant : | ||
+ | |||
+ | * lever l'ambiguité sur un conflit entre des noms de fonctions ou de champs, notamment quand il y a une fonction ou un champ qui est défini plusieurs fois dans des contextes différents, cela permet de préciser que l'on souhaite accéder au champ ou à la méthode défini dans la classe en préfixant le nom du membre ou de la méthode par ''this->''.\\ <code cpp> | ||
+ | bool Value::is_equal(const A& anotherValue) const | ||
+ | { | ||
+ | return this->m_value == anotherObject.m_value; | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | * permettre à la fonction de retourner une référence à l'objet, soit sous la forme d'un pointeur, soit au contraire sous la forme d'une référence.\\ <code cpp> | ||
+ | Value& Value::operator+=(const A& anotherValue) | ||
+ | { | ||
+ | this->m_value += anotherValue.m_value; | ||
+ | return *this; | ||
+ | } | ||
+ | </code> | ||
+ | * peremttre de dupliquer l'objet en appelant un constructeur qui attend une référence à l'objet ou de passer la référence de l'objet à une fonction qui attendrait une telle référence.\\ <code cpp> | ||
+ | Value& Value::operator++(int) | ||
+ | { | ||
+ | Value value(*this); | ||
+ | this->m_value ++; | ||
+ | return value; | ||
+ | } | ||
+ | </code> | ||
===== Différence entre ''class'' et ''struct'' ===== | ===== Différence entre ''class'' et ''struct'' ===== | ||
Line 184: | Line 308: | ||
</code> | </code> | ||
- | ===== Les sections internes d'une classe ===== | ||
- | |||
- | Les mots clés ''private'', ''protected'' et ''public'' modifient la visibilité des différents éléments dans une classe. Pour plus d'informations, le chapitre détaille les différents niveaux [[in204:cpp:syntax:public|d'accessibilité aux champs et membres]] notamment dans le cadre de l'héritage. | ||
- | |||
- | * Un élément d'une classe est dit ''public'' s'il est accessible à la fois par les fonctions membres de la classe mais aussi par les autres fonctions (fonctions du programme ou fonctions membres d'une autre classe). | ||
- | |||
- | * Un élément d'une classe est dit ''private'' s'il est accessible par les fonctions membres de la classe mais aussi par n'est pas visible par les autres fonctions (fonctions du programme ou fonctions membres d'une autre classe). | ||
- | |||
- | <code cpp> | ||
- | class Point | ||
- | { | ||
- | private: | ||
- | double x; // les champs x et y sont déclarées privées | ||
- | double y; // ils ne pourront qu'être accédés par les méthodes | ||
- | // internes de la classe. | ||
- | public: | ||
- | int getX() const { return x; } // accède au champ x. | ||
- | int getY() const { return y; } // accède au champ y. | ||
- | |||
- | } | ||
- | </code> | ||
- | |||
- | En conséquence : | ||
- | |||
- | <code cpp> | ||
- | |||
- | int main() | ||
- | { | ||
- | Point p; | ||
- | | ||
- | std::cout << "L'abcisse de p est " << p.getX() << std::endl; | ||
- | // L'accès à la méthode p est possible par ce que la fonction membre | ||
- | // getX est publique. | ||
- | | ||
- | std::cout << "L'abcisse de p est " << p.x << std::endl; | ||
- | // L'accès au champ p est impossible par ce que le champ | ||
- | // p n'est pas public. | ||
- | } | ||
- | | ||
- | </code> | ||