56 votes

Éviter la conversion implicite dans le constructeur. Le mot clé "explicit" n'est pas utile ici.

Je suis en mesure d'éviter la conversion implicite d'un constructeur à l'aide de la balise explicit mot-clé. Donc maintenant, les conversions comme A a1 = 10; peut être évitée.

Mais je peux toujours initialiser A a1 = A(20.2); . Comment puis-je désactiver la création d'objet de sorte qu'un objet ne puisse être créé que si nous passons un entier comme paramètre, par exemple. A a1 = A(10) ?

#include <iostream>

class A
{
public:
    explicit A(int a)
    {
        num = a;
    }

    int num;
};

int main()
{
    A a1 = A(10.0);
    std::cout << a1.num;
    return 0;
}

75voto

YSC Points 3386

Puedes delete A::A(<anything not an int>); :

struct A
{
    explicit A(int a)
    : num(a)
    {}

    template<class T>
    A(T) = delete;

    int num;
};

int main()
{
    //A a1=A(10.0); // error: use of deleted function 'A::A(T) [with T = double]'
    A a2 = A(10); // OK
    (void) a2;
}

Démonstration : https://coliru.stacked-crooked.com/a/425afc19003697c9

5 votes

@Alexander Le C++ est l'un des plus anciens langages de haut niveau qui est encore activement utilisé dans de nouveaux projets. Les seuls langages plus anciens et toujours activement utilisés AFAIK sont FORTRAN, COBOL et LISP. En conséquence, le C++ a BEAUCOUP plus de flexibilité que des langages plus jeunes comme Java ou C#, mais cette flexibilité a un prix : il est beaucoup plus facile de faire des erreurs.

0 votes

@Nzall La flexibilité, c'est bien, mais la conversion implicite par défaut me semble insensée. Je n'ai pas beaucoup utilisé C#, mais je sais qu'il a des opérateurs de conversion implicites, mais ils ne sont pas par défaut, et nécessitent un opt-in explicite (contrairement à ce qui se passe ici, où explicit doit être explicitement déclarée pour refuser un comportement implicite). Dans le même ordre d'idées, j'ai également vraiment souhaité const était la valeur par défaut. Le compilateur peut détecter une référence non-const à une variable const, et vous demander d'écrire mutating (ou quelque chose comme ça). Mais il n'a jamais suggéré "ceci peut (devrait ?) être const, btw", dans aucun compilateur/IDE que j'ai vu

4 votes

@Alexander "La conversion implicite par défaut me semble insensée" Cela semble insensé à tous les développeurs C++. Mais le choix a été fait il y a des lustres et nous en payons tous le prix aujourd'hui.

31voto

NathanOliver Points 10062

La façon d'y parvenir est de fournir un autre constructeur qui correspondrait mieux, et ensuite delete alors vous obtiendrez une erreur. Pour votre classe, en ajoutant

template <typename T>
A(T) = delete;

Empêchera la classe d'être construite à partir de n'importe quel élément qui n'est pas un int

8voto

IHopeImHelpful Points 81

Vous pouvez contourner ce problème en utilisant une initialisation entre accolades. Par exemple :

struct A {
  A(int _a) : a(_a) {}
  int a;
};

A a{5}; // ok
A b{1.123}; // compile error

Preuve

6voto

bracco23 Points 945

Je veux juste ajouter que le A(double) = delete est un C++11 addition.

Si, pour une raison quelconque, vous ne pouvez pas utiliser cette construction relativement nouvelle, vous pouvez simplement la déclarer comme privée :

class A{
  public:
    A(int);
  private:
    A(double);
}

5voto

RiaD Points 15744

Pour éviter les conversions int->double partout, et pas seulement dans votre cas. Avec g++, vous pouvez utiliser -Wconversion -Werror . Notez qu'il sera autorisé dans votre cas particulier, car le compilateur comprend que 10.0 est littéral, mais il échouera à la compilation pour :

class A
{
public:
    explicit A(int a)
    {
        num = a;
    }

    int num;
};

int main()
{
    double x = 10;
    A a1 = A(x);
    static_cast<void>(a1);
    return 0;
}

Explorateur de compilateurs

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