2.2- Objets


1 Classes

2 Construction et destruction d'objets

3 Définition et déclaration


1 Classes

La programmation objet consiste en la déclaration et l'utilisation de classes créées par l'utilisateur.

Déclaration de classe

La déclaration se fait de la manière suivante :

class Action
{
	double coursDuJour;
	double coursAncien;

	double calcRentabilite();
};

Ici on définit une classe Action qui donne le cours du jour, le coursAncien et définit le calcul de la rentabilité. En définissant la classe de cette manière, et si le stockage d'un double représente bien 8 octets, alors le stockage d'un objet Action prendra 16 octets en mémoire.
Autant que faire se peut, le nom retenu des variables/ attributs et des fonctions doit être significatif.

Déclaration d'une variable objet

Il s'agit ici de définir une variable qui contient un objet. Par opposition à ce type de variable, on parle de types primitifs pour les types int, double, float etc. La définition des variables de type objet se fait à l'instar des variables de type primitif :

Action societeGenerale;
Par suite, il est possible d'utilise les attributs et les fonctions de la classe :
societeGenerale.coursDuJour=5;
double variationEnValeur=societeGenerale.coursDuJour-societeGenerale.coursAncien;
double rentabilite=calcRentabilite();

Private / Public

Par défaut, tous les attributs et toutes les méthodes sont privées. Pour des attributs et des méthodes privées, il ne sont utilisables que dans les méthodes de l'objet qui les définis. Vous pouvez vous réferez à l'introduction sur la programmation objet pour la notion de visibilité. Ainsi, le code suivant produit une erreur :

#include <iostream>

class Action
{
	double coursDuJour;
	double coursAncien;

	double calcRentabilite();
};


int main()
	{
	Action societeGenerale;
	societeGenerale.coursDuJour=77.54;
	}

Pour déclarer comme public les attributs et les méthodes d'une classe :

#include <iostream>

class Action
{
public :
	double coursDuJour;
	double coursAncien;

	double calcRentabilite();
};


int main()
	{
	Action societeGenerale;
	societeGenerale.coursDuJour=77.54;
	}

De manière générale pour une classe pour laquelle il y a des attributs / méthodes de visibilité privée et des attributs / méthodes de visbilité public :

class Action
{
public :
	double coursDuJour;
	double coursAncien;
	double calcRentabilite();
private : 
	double reference;
};

Implémentation des méthodes d'une classe

L'implémentation des méthodes de la classe se fait de la manière suivante :

#include <iostream>

class Action
{
public :
	double coursDuJour;
	double coursAncien;
	double calcRentabilite();
private : 
	double reference;
};


double Action::calcRentabilite()
	{
	double intermediaire=(coursDuJour-coursAncien)/coursAncien;
	return intermediaire;
	}

/*La fonction main ne contient ici aucune instruction*/
int main()
	{
	}

2 Construction d'objets

Constructeur

On présente ici une première manière de construire des objets, ce ne sera pas la méthode la plus utilisée une fois que nous aurons abordé les pointeurs. Dans ce qui suit, on parle de création statique. Par opposition, c'est la création dynamique qui sera présentée plus loin.
Dans les deux cas, la création d'un objet se fait à l'aide d'une fonction particulière : le constructeur. Soit une classe telle qu'aucun constructeur n'a été défini, par exemple, la classe Action du listing précédent. Dans ce cas, c'est le constructeur par défaut qui est utilisé :
Action societeGenerale;
L'instruction suffit ici à créer un objet de type Action. On peut manipuler les attributs de Action :
#include <iostream>

class Action
{
public :
	double coursDuJour;
	double coursAncien;
	double calcRentabilite();
private : 
	double reference;
};


double Action::calcRentabilite()
	{
	double intermediaire=(coursDuJour-coursAncien)/coursAncien;
	return intermediaire;
	}

/*La fonction main ne contient ici aucune instruction*/
int main()
	{
	Action societeGenerale;
	societeGenerale.coursAncien=6;
	std::cout << societeGenerale.coursDuJour << " " << societeGenerale.coursAncien << " "; 
	}
On peut vouloir forcer le passage de certains paramètres pour la construction d'un objet. Par exemple, on peut vouloir exiger qu'une Action soit créée avec une référence. Dans ce cas, on déclare le constructeur :

class Action
{
public :
	double coursDuJour;
	double coursAncien;
	double calcRentabilite();
	Action(double reference);
private : 
	double reference;
};
et on donne le corps de la fonction-constructeur :
Action::Action(double ref)
	{
	reference=ref;
	}
Il est également possible de surcharger le constructeur et notamment de réintroduire le constructeur par défaut :
#include <iostream>

class Action
{
public :
	double coursDuJour;
	double coursAncien;
	double calcRentabilite();
	Action(double ref);
	Action(double ref,double coursDuJour);
	Action();
private : 
	double reference;
};


double Action::calcRentabilite()
	{
	double intermediaire=(coursDuJour-coursAncien)/coursAncien;
	return intermediaire;
	}

Action::Action(double ref)
	{
	reference=ref;
	}

Action::Action(double ref,double x)
	{
	reference=ref;
	coursDuJour=x;
	}

Action::Action()
	{
	}

/*La fonction main ne contient ici aucune instruction*/
int main()
	{
	Action societeGenerale;
	societeGenerale.coursAncien=6;
	std::cout << societeGenerale.coursDuJour << " " << societeGenerale.coursAncien << "\n"; 
	Action bnp(5,29.7);
	std::cout << bnp.coursDuJour << " " << bnp.coursAncien << "\n"; 
	}

Méthode constante

Il est possible d'utiliser le mot clé const sur une méthode. Ce mot clé indique la fonction ne contient aucune instruction de modification des membres de la classe. Ainsi dans le code qui suit, la fonction f1

ExFonctionConst
#include <iostream>

class A
{
public : 
	int j;
	void f1() const;
	void f2();
	void f3() const;
	A();
};

void A::f1() const
	{
	j=5;
	}

void A::f2()
	{
	j=5;
	}

void A::f3() const
	{
	std::cout << "Ceci vient de f3\n";
	}

A::A()
	{
	std::cout << "Appel au constructeur\n";
	}

int main()
	{
	A varA;
	varA.f1();
	varA.f2();
	varA.f3();
	return 0;
	}

Ceci provoque une erreur à la compilation à cause de la fonction f1 déclarée comme const mais qui contient une instruction de modification de j. En revanche, le code suivant se compile :

#include <iostream>

class A
{
public : 
	int j;
	void f1() const;
	void f2();
	void f3() const;
	A();
};

void A::f1() const
	{
	std::cout << "Ceci vient de f1\n";
	}

void A::f2()
	{
	j=5;
	}

void A::f3() const
	{
	std::cout << "Ceci vient de f3\n";
	}

A::A()
	{
	std::cout << "Appel au constructeur\n";
	}

int main()
	{
	A varA;
	varA.f1();
	varA.f2();
	varA.f3();
	return 0;
	}

Autant que faire se peut, il vaut mieux déclarer comme const les fonctions qui le sont, pour que le compilateur puisse détecter d'éventuelles erreurs.

3 Défnition et déclaration

La définition d'une fonction est son implémentation. Comme pour les autres fonctions, la définition d'une méthode de classe comprend un en-tête et un corps de fonction. la définition est un fichier dont le chemin d'accès doit être connu du compilateur. Par ailleurs, ce fichier doit inclure l'extension c ou cpp. Il est possible de placer la déclaration dans le fichier source principal, mais c'est assez peu recommandé. Par convention, on écrit la déclaration dans un fichier en tête portant le même nom que le fichier source mais suivi de l'extension .h, .hp ou .hpp (h pour header).
Un exemple de séparation. La classe Action est déclarée dans un fichier .hpp Action.hpp :

class Action
	{
private : 
	double coursAvt;
	double coursAp;
public : 	
	double calcRentabilite();
	void affichageCoursAvt() const;
	void affichageCoursApres() const;
	Action(double a,double b);
	};

Attention certains compilateurs exige que les fichiers headers se terminent par un saut de ligne. Le code est ensuite placé dans un fichier ExecuteAction.cpp :
#include <iostream>
#include "Action.hpp"

double Action::calcRentabilite()
	{
	return (coursAp-coursAvt)/coursAvt;
	}

Action::Action(double a,double b)
	{
	coursAvt=a;
	coursAp=b;
	}

void Action::affichageCoursAvt() const
	{
	std::cout << "cours avant : " << coursAvt << "\n";
	}

void Action::affichageCoursApres() const
	{
	std::cout << "cours apres : " << coursAp << "\n";
	}

int main()
	{
	Action sg(120,20);
	sg.affichageCoursAvt();
	sg.affichageCoursApres();
	std::cout << "Le calcul de rentabilite donne : " << sg.calcRentabilite() << "\n";
	return 0;
	}


Le fichier Action.hpp est comme inclut dans le fichier ExecuteAction.cpp.