Règles pour développer des applications C++

Règles pour coder en C++

Règles pour coder en C++ efficacement

Développer avec le langage C++ en entreprise demande des règles de programmation. En voici quelques unes. Ce sont pour ma part les plus importantes, certaines sont contestables, mais l’expérience prouve que la plupart sont incontournables.

1. Toujours mettre à NULL (ou nullptr) les pointeurs non utilisés ou invalides.

class X {};
X * p = NULL; // utilisez nullptr en C++11

Et ce, même dans un destructeur (voir ci-dessous).

class X {
private:
    Y * _py;
public:
    // ...
    ~X() {
        if( NULL != _py ) {
            delete _py;
            _py = NULL;
        }
    }
};

2. Dans une classe C++ il faut toujours créer un constructeur par défaut.

class X {
public:
     X() {} // constructeur par défaut
};

3. Dans une classe C++ toujours créer un destructeur, et de plus préfixé ‘virtual‘.

class X {
public:
     virtual ~X() {} // destructeur virtuel
};

4. Déclarer tous les constructeurs en ‘explicit‘.

class X {
public:
    X();
    explicit X( const X& ); // constructeur par copie explicite
};

int main() {
     X x1;
     X x2 = x1; // KO
     X x3(x1);  // OK
     return 0;
}

5. Pour tous les accesseurs en lecture de votre classe (le plus souvent les méthodes Get…(), suffixer ces méthodes const.

class Point {
    //...
public:
    double getX();       // Mauvaise pratique
    double getY() const; // Bonne pratique
};

int main() {
    const Point p1;
    double x = p1.getX();    // KO, le compilateur n'est pas d'accord !
    double y = p1.getY();    // OK
    return 0;
}

6. Dans une classe C++, s’il existe au moins un attribut pointeur, toujours créer un constructeur par copie (si l’objet est copiable), ou le déclarer en privé sans l’implémenter.

class Segment {
private:
    Point * p1, * p2;
private:
    Segment( const Segment& ); // ici constructeur par copie en privé
public:
    Segment( const Point&, const Point& );
};

7. Dans une classe C++, s’il existe au moins un attribut pointeur, toujours surcharger l’opérateur = (si l’objet est copiable), ou le déclarer en privé sans l’implementer (si l’objet est non copiable).

class Segment {
private:
    Point * p1, * p2;
private:
    Segment& operator = (const Segment&); // ici opérateur = en privé
public:
    Segment( const Point&, const Point& );
};

8. Ne pas utiliser l’héritage privé

class A {};
class B : private A {}; // A éviter
A * pa = new B() ; // KO

9. Eviter d’utiliser l’héritage multiple

class Base {};
class A : public Base {};
class B : public Base {};
class C : public A, public B {}; // A éviter

En effet le constructeur et le destructeur de la classe de base sera appelé 2 fois dans ce cas.

10. Eviter l’appel de méthodes virtuelles dans un constructeur ou dans un destructeur.

class Figure {
public:
    Figure() {
        init(); // Ici à ne pas faire, le compilateur va refuser
    }
    virtual void init() = 0;
};

class Cercle : public Figure {
public:
    Cercle() {}
    virtual void init() {}
};
Catégories
0 Comments
0 Pings & Trackbacks

Laisser un commentaire