Archive pour juin 2011

De l’utilisation du const en Programmation Objet

Vendredi 10 juin 2011

Une chose est sur le mot clé const est bien souvent négligé. Alors que ce mot clé existe depuis le C, mais la programmation Objet lui confère de nouvelles possibilitées. Donc je partirai du principe que vous maitrisé l’utilisation du const en C. Juste ce petit rappel:

[sourcecode language="cpp"]
int function1(int& i) // ok
{
return ++i ; //On modifie i et on a le droit
}
int function2(const int i) // ok
{
int a = i ;
//return ++i ; error C3892: ‘i’ : you cannot assign to a variable that is const
return a+1 ;
}
int function3(const int& i)
{
int a = i ;
//return ++i ; error C3892: ‘i’ : you cannot assign to a variable that is const
return a+1;
}[/sourcecode]

Rentrons maintenant dans le vif du sujet, l’utilisation du const en PO. Pour présenté, je vais vous parler des accesseurs.

[sourcecode language="cpp"]
class Usage
{
int m;
public:
const int& get() const { return this->m; }
void set(const int& v) { this->m = v ; }
};[/sourcecode]

Pour accéder au membre m de la classe il est préférable de ne pas la déclaré en public mais d’ajouter deux fonctions membres get et set. Ici pour simplifié l’exemple le type du membre m est de type int, l’utilisation de passage par référence n’est donc pas là pour la réduction d’utilisation de la mémoire mais comme exemple.
En effet, la fonction membre m déclaré comme const, informe que l’appel de cette fonction ne pourra modifier aucun de ses membres.

Utilisation d’un membre const

Une autre possibilité est l’utilisation d’un membre const, celui-ci devra est obligatoirement affecté dès le début du constructeur, comme-ci:
[sourcecode language="cpp"]
class Usage
{
const int mc;
public:
Usage(const int& v) : mc(v) {}
Usage(const int& v) { mc = v; } //ERREUR
void set(const int& v) { mc = v; } //ERREUR
};[/sourcecode]
Mais à quoi donc cela peut bien servir? Voici un petit exemple :
[sourcecode language="cpp"]
#include <string>
class Usage
{
const std::string mObjectName ;
public:
Usage(const std::string& name) : mObjectName(name) {}
};[/sourcecode]
Le nom de l’objet est affecté dès la construction de celui-ci et ne sera plus jamais modifiable jusqu’à la fin de sa vie.

Const et l’héritage

Il est tout à faire possible et même conseillé d’hérité des fonctions const :
[sourcecode language="cpp"]
class UsageBase
{
virtual void override() const = 0 ;
};
class Usage : public UsageBase
{
virtual void override() const { //fait des choses mais sans affecté les membres }
};
[/sourcecode]

Const et la STL

Il faut savoir une petit chose sur l’utilisation des itérateurs et le mot clé const, il existe son homologue const_iterator, les STL sont quand même bien faites!
[sourcecode language="cpp"]
class Usage
{
std::vector<int> ml;
bool find(const int& v) const
{
std::vector<int>::const_iterator it = ml.begin();
for( ; it != ml.end(); it++ )
if ( v == *it )
return true;
return false ;
}
};
[/sourcecode]

Une autre astuce est par exemple lors de l’utilisation de section critique, ou de systeme de cache. En effet, l’utilisation de la section critique n’est pas compatible avec le const, il faut donc utiliser le mot clef mutable sur la section critique pour que l’on puisse garder l’attribut const.
[sourcecode language="cpp"]
class Usage
{
mutable CriticalSection cs;
std::vector<int> ml;
int get(int idx) const
{
cs.get(); int ret = ml.at(idx); cs.leave(); return ret ;
}
};
[/sourcecode]
Maintenant que vous savez tous sur les const, n’hésiter plus à l’employer à toutes les sauces !