6
votes

Passer la classe au constructeur, lorsqu'aucun constructeur de ce type n'existe. Pourquoi ça marche?

J'ai une classe qui ressemble à:

A* a = new A(1.0);
A* b = new A(*a);

Ensuite, j'instancie 2 objets de classe A:

class A {
public:
    A(float v) 
    { 
        A::v = v; 
    }
    float v;
    float set(float v) 
    {
        A::v = v;
        return v;
    }
    float get(float v) 
    {
        return A::v;
    }
};

Pourquoi il n'y a pas d'erreurs quand ma classe A n'a pas de constructeur qui prend une classe A?


8 commentaires

À part: get prend un argument: float get (float v) - mais ce n'est pas une attente / idiome courante. Vous voudrez peut-être changer cela.


Êtes-vous sûr que votre livre ne couvre pas cela?


Surpris, le surligneur de syntaxe a sorti set . Ish


@LightnessRacesinOrbit: À quoi le monde arrive-t-il?


@Bathsheba Une fin. Lentement :)


@NathanOliver Pourquoi ne pas le duper? Je suis sûr que nous avons eu une question similaire hier, même si je ne la trouve pas pour le moment ...


@BrianCain Je ne ferais pas ça si c'était mon propre code. Cela faisait partie d'un quiz que j'ai pris, donc le passage d'arguments a probablement été fait pour semer la confusion lorsqu'il était utilisé dans une autre partie du code (qui n'est pas incluse dans l'extrait de code) :)


@MaxLanghof Je ne l'ai pas fait parce que les réponses ici expliquent comment obtenir le comportement souhaité par l'OP, ce qui n'est pas couvert par la dupe. Je ne voulais pas le fermer unilatéralement.


3 Réponses :


11
votes

Le compilateur génère un constructeur de copie pour vous:

Si aucun constructeur de copie défini par l'utilisateur n'est fourni pour un type de classe (struct, classe ou union), le compilateur déclarera toujours un constructeur de copie comme membre public en ligne non explicite de sa classe.

Vous pouvez supprimer le constructeur de copie et l'affectation et empêcher le compilateur de déclarer l'affectation et le constructeur de déplacement en déclarant l'un des constructeurs ou affectations de déplacement comme supprimés:

A(A&&) = delete; // Makes the class non-copyable and non-moveable.


4 commentaires

Upvoté car il semble que j'ai plagié votre extrait! (N'hésitez pas à inclure également des éléments de ma réponse - cela me semble être la meilleure réponse de la culture actuelle).


N'y a-t-il vraiment aucune dupe qui couvre cela? Voilà beaucoup de réponses à une question que je pourrais jurer avoir vue hier ...


@Bathsheba Yours est une bête assez rare A (A const &&) .


@MaximEgorushkin: Dernière édition et un wiki comme promis. Ce n'est plus "ma" réponse!



5
votes

Un constructeur de copie implicite est généré par le compilateur, si vous ne spécifiez pas de propre.

Une autre remarque:

Essayez

A a = 3.0f;

Conclusion: marquez toujours les constructeurs qui prennent un seul type de données de base comme explicite ... sauf si vous aimez la conversion implicite


4 commentaires

"marquez toujours les constructeurs qui prennent un seul type de données de base comme explicite" ... sauf si vous aimez la conversion implicite.


Cet avis est dépassé; vous devez également marquer les constructeurs multi-arguments comme explicites pour éviter l'initialisation à l'aide de {} .


@Bathsheba Je dirais que vous êtes encore moins susceptible de vouloir les expliquer , mais c'est possible


@BrianCain, bien sûr, vous avez raison. mais d'après mon expérience, c'est assez rare, peut-être si vous implémentez une classe de nombres qui devrait se comporter de manière transparente.



8
votes

Il a le constructeur de copie: le compilateur en a généré un pour vous.

Si vous voulez désactiver cela explicitement, écrivez

A(A&&) = delete;

dans la déclaration de classe; et utiliser

A(const A&) = delete;

supprime toutes la règle des cinq fonctions, à l'exception du destructeur.

p >


4 commentaires

Le compilateur génère cependant toujours l'opérateur d'affectation.


@MaximEgorushkin: Oui, en effet, a ajouté la manière idiomatique de gérer cela.


nitpick: destructeur toujours généré


Un autre correctif et je vais wiki ceci!