3502 votes

Qu'est-ce que le WOW signifie?

Quelqu'un a posté dans un commentaire à une autre question sur le sens de l' explicit mot-clé en C++. Donc, ça veut dire quoi?

3999voto

Skizz Points 30682

En C++, le compilateur est autorisé à faire une conversion implicite pour régler les paramètres d'une fonction. Ce que cela signifie, c'est que le compilateur peut utiliser seul paramètre constructeurs pour convertir d'un type à l'autre afin d'obtenir le bon type d'un paramètre. Voici un exemple de classe avec un constructeur qui peut être utilisé pour les conversions implicites:

class Foo
{
public:
  // single parameter constructor, can be used as an implicit conversion
  Foo (int foo) : m_foo (foo) 
  {
  }

  int GetFoo () { return m_foo; }

private:
  int m_foo;
};

Voici une fonction qui prend un Foo objet:

void DoBar (Foo foo)
{
  int i = foo.GetFoo ();
}

et c'est ici où la DoBar fonction est appelée.

int main ()
{
  DoBar (42);
}

Le paramètre n'est pas un Foo objet, mais un int. Cependant, il existe un constructeur Foo qui prend un int donc ce constructeur peut être utilisé pour convertir le paramètre le type correct.

Le compilateur est autorisé à le faire une fois pour chaque paramètre.

Le préfixe explicit mot-clé pour le constructeur empêche le compilateur d'utiliser le constructeur pour les conversions implicites. Ajouter à la classe ci-dessus va créer une erreur de compilation, à l'appel de la fonction DoBar (42). Il est maintenant nécessaire de faire appel à la conversion explicitement DoBar (Foo (42))

La raison pour laquelle vous pourriez vouloir faire cela est pour éviter les blessures accidentelles de construction qui peuvent cacher des bugs. Exemple artificiel:

  • Vous avez un MyString(int size) classe avec un constructeur qui construit une chaîne de taille donnée. Vous avez une fonction print(const MyString&), et vous l'appelez avec print(3). Vous vous attendez à imprimer "3", mais il imprime une chaîne de caractères vide de longueur 3 à la place.

1292voto

Eddie Points 3931

Supposons que vous avez une Chaîne de classe

class String {
public: 
    String(int n); // allocate n bytes to the String object 
    String(const char *p); // initializes object with char *p 
} 

Maintenant, si vous essayez

String mystring = 'x';

le caractère " x " seront convertis en int et fera appel à Cordes(int) constructeur. Mais ce n'est pas ce que l'utilisateur pourrait avoir prévu. Afin de prévenir de telles conditions, on peut définir le constructeur de la classe la plus explicite.

class String { 
public: 
    explicit String (int n); //allocate n bytes
    String(const char *p); // initialize sobject with string p 
} 

191voto

cjm Points 44090

En C++, un constructeur avec un seul paramètre obligatoire est considéré comme une conversion implicite de la fonction. Il convertit le paramètre de type de la classe type. Si c'est une bonne chose ou pas dépend de la sémantique du constructeur.

Par exemple, si vous avez une chaîne de classe avec un constructeur String(const char* s), c'est probablement exactement ce que vous voulez. Vous pouvez passer une const char* à une fonction attend un String, et le compilateur va construire automatiquement une temporaire String objet pour vous.

D'autre part, si vous avez un tampon de classe dont le constructeur Buffer(int size) prend la taille de la mémoire tampon en octets, vous ne voulez probablement pas le compilateur tranquillement tourner ints dans Buffers. Pour éviter cela, vous déclarer le constructeur avec l' explicit mot-clé:

class Buffer { explicit Buffer(int size); ... }

De cette façon,

void useBuffer(Buffer& buf);
useBuffer(4);

devient une erreur de compilation. Si vous souhaitez passer un temporaire Buffer objet, vous devez le faire de manière explicite:

useBuffer(Buffer(4));

En résumé, si votre seul paramètre du constructeur convertit le paramètre un objet de votre classe, vous ne voulez probablement pas à utiliser l' explicit mot-clé. Mais si vous avez un constructeur qui prendre qu'un seul paramètre, vous devez le déclarer comme explicit pour empêcher le compilateur de vous surprendre avec des conversions inattendues.

57voto

Gautam Points 307

Cette réponse est à propos de la création d'un objet avec/sans explicitement un constructeur, car il n'est pas couvert dans les autres réponses.

Considérez les points suivants de la classe sans un constructeur explicite:

class Foo
{
public:
    Foo(int x) : m_x(x)
    {
    }

private:
    int m_x;
};

Les objets de la classe Foo peuvent être créés de 2 façons:

Foo bar1(10);

Foo bar2 = 20;

En fonction de la mise en œuvre, la seconde manière de l'instanciation de la classe Foo peut être source de confusion, ou pas ce que le programmeur a prévu. Le préfixe explicit mot-clé pour le constructeur serait de générer une erreur de compilation, en Foo bar2 = 20;.

Il est généralement une bonne pratique de déclarer seul argument des constructeurs comme explicit, à moins que votre mise en œuvre spécifiquement interdit.

Notez également que les constructeurs avec

  • les arguments par défaut pour tous les paramètres, ou
  • les arguments par défaut pour le deuxième paramètre à partir de

peut à la fois être utilisé comme unique argument des constructeurs. De sorte que vous pouvez faire ces aussi explicit.

Un exemple lorsque vous auraient délibérément de ne pas vous voulez faire de votre unique argument du constructeur explicite est si vous êtes à la création d'un foncteur (regardez le "add_x' struct a déclaré à cette réponse). Dans un tel cas, la création d'un objet en tant que add_x add30 = 30; serait probablement logique.

Ici est un bon d'écrire-up sur explicite des constructeurs.

47voto

SankararaoMajji Points 131

L' explicit mot clé permet une conversion constructeur de non-conversion constructeur. En conséquence, le code est moins sujette aux erreurs.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X