samedi 19 juin 2010

C++0x - Default et delete explicites

Ce n'est pas vraiment une révolution, mais c'est une fonctionnalité plutôt agréable de C++0x: la possibilité de spécifier explicitement ses constructeurs par défaut, ou leur absence.

La syntaxe est des plus simples, voyez donc mon entity factory:


class EntityFactory
{
public:
EntityFactory() = default;
EntityFactory(const EntityFactory &) = delete;
EntityFactory & operator=(const EntityFactory &) = delete;
virtual ~EntityFactory() = default;
};

Cette signature indique que le constructeur par défaut "est" le constructeur par défaut, qu'il n'y a pas de constructeur par copie, pas d'assignement, et enfin que le destructeur par défaut "est" le destructeur par défaut.

La suppression du constructeur par copie et de l'assignement se faisaient généralement soit manuellement, en les déclarant privés (ce qui prenait un poil plus de place), ou en dérivant de la bonne vieille boost::noncopyable, ce qui prenait plutôt moins de place. La méthode "A la mano" est à mon avis la moins bonne, puisque la moins explicite. Entre boost et le delete C++0x, mon cœur balance, il faudra donc voir à l'usage.

Par contre, la possibilité de définir le destructeur virtuel par défaut est vraiment bien. et évite d'avoir à se farcir un corps de méthode vide.

Attention cependant! La règle qui dit que définir un constructeur supprime le constructeur par défaut implicite est encore valide. Ansi, ce petit programme:

class A
{
public:
A(const A &) = delete;
A & operator=(const A &) = default;
};

int main()
{
A a;
return 0;
}

ne fonctionnera pas comme prévu, et jettera le message "error: no matching function for call to ‘A::A()’". En effet, définir ne serais-ce que l'absence du constructeur par copie supprime le constructeur par défaut implicite.

Le programme correct est donc:

class A
{
public:
A() = default;
A(const A &) = delete;
A & operator=(const A &) = default;
};

int main()
{
A a;
return 0;
}

Aucun commentaire: