2010-09-17 4 views
0

copie Je veux appliquer la conversion explicite entre struct un peu comme les types natifs:C++ - opérateur d'affectation appel à la création au lieu de constructeur

int i1; 
i1 = some_float; // this generates a warning 
i1 = int(some_float): // this is OK 
int i3 = some_float; // this generates a warning 

Je pensais que d'utiliser un opérateur d'affectation et de copie constructeur pour faire la même chose , mais le comportement est différent:

Struct s1; 
s1 = other_struct; // this calls the assignment operator which generates my warning 
s1 = Struct(other_struct) // this calls the copy constructor to generate a new Struct and then passes that new instance to s1's assignment operator 
Struct s3 = other_struct; // this calls the COPY CONSTRUCTOR and succeeds with no warning 

y a-t-il des astuces pour obtenir ce troisième cas Struct s3 = other_struct; construction s3 avec le constructeur par défaut, puis appeler l'opérateur d'affectation?

Tout cela se compile et s'exécute comme il se doit. Le comportement par défaut de C++ consiste à appeler le constructeur de copie au lieu de l'opérateur d'affectation lorsque vous créez une nouvelle instance et appelez le constructeur de copie à la fois, (par exemple, MyStruct s = other_struct; devient MyStruct s(other_struct) et non MyStruct s; s = other_struct;. astuces pour contourner cette

EDIT:. Le mot-clé "explicite" est juste ce que je devais

class foo { 
    foo(const foo& f) { ... } 
    explicit foo(const bar& b) { ... } 
    foo& operator =(const foo& f) { ... } 
}; 

foo f; 
bar b; 
foo f2 = f; // this works 
foo f3 = b; // this doesn't, thanks to the explicit keyword! 
foo f4 = foo(b); // this works - you're forced to do an "explicit conversion" 
+0

Postez une version abrégée du code réel s'il vous plaît. Affichez également les avertissements et les erreurs. Il me semble que vous voulez faire quelque chose de vraiment stupide et le compilateur vous le dit. –

+0

@San Jacinto: Je pense que Chris veut écrire des classes de telle sorte que * si * Chris (ou quelqu'un d'autre) fait quelque chose de vraiment idiot, alors le compilateur le dira. –

+0

Attendez, cette question a-t-elle fondamentalement changé? –

Répondre

3

Vous pouvez contourner ce problème si vous surchargez l'opérateur de conversion de type pour other_struct et modifiez la structure d'origine en conséquence. Cela dit, c'est extrêmement désordonné et il n'y a généralement pas de bonne raison de le faire.


#include <iostream> 

using namespace std; 

struct bar; 

struct foo { 
    explicit foo() { 
     cout << "In foo default constructor." << endl; 
    } 

    explicit foo(bar const &) { 
     cout << "In foo 'bar' contructor." << endl; 
    } 

    foo(foo const &) { 
     cout << "In foo constructor." << endl; 
    } 

    foo const & operator=(bar const &) { 
     cout << "In foo = operator." << endl; 
     return *this; 
    } 
}; 

struct bar { 
    operator foo() { 
     cout << "In bar cast overload." << endl; 
     foo x; 
     x = *this; 
     return x; 
    } 
}; 

int main() { 
    bar b; 
    foo f = b; 
    return 0; 
} 

Sorties:

In bar cast overload. 
In foo default constructor. 
In foo = operator. 
In foo constructor. 
In foo constructor. 
+0

Appelé le constructeur de copie deux fois. –

+0

@Noah: Je crois que c'est parce que le compilateur ne peut pas optimiser la copie créée à partir de l'opérateur de distribution quand il revient. – Paul

+0

Peut-être. Le point est qu'il ne fournit pas à l'OP ce qu'ils veulent. Bien sûr, il ajoute un appel à l'opérateur d'affectation, mais cela ne change pas la nature essentielle de Type t = x. La variable est toujours construite avec le constructeur de copie. Tout ce que vous avez fait est d'insérer un temporaire qui est créé avec le + op = par défaut. –

2

En bref, pas

La version longue ... en fait c'est tout!.. Ce n'est pas comme ça que ça marche. e avec quelque chose pour remplir l'exigence de personnage si.

+0

Version longue possible: 'MyStruct s (other_struct)' n'est pas plus ou moins une conversion que 'MyStruct s = other_struct'. Dans les deux cas, vous indiquez le type de 's', juste là sur cette ligne de code, mais pas le type de' other_struct'. Alors pourquoi devraient-ils être différents de la POV de la conversion explicite/implicite? Et en effet, ils ne le sont pas. –

0

Je ne pense pas. Lorsque vous écrivez

Struct s3 = other_struct; 

Cela ressemble à une affectation, mais c'est vraiment une syntaxe déclarative qui appelle un constructeur.

4

Disclaimer: Je suis prêt à prendre les downvotes à ce sujet, étant donné que cela ne répond pas à la question. Mais cela pourrait être utile à l'OP.

Je pense que c'est une très mauvaise idée de penser au constructeur de copie comme construction + affectation par défaut. Il est l'inverse:

struct some_struct 
{ 
    some_struct(); // If you want a default constructor, fine 
    some_struct(some_struct const&); // Implement it in the most natural way 
    some_struct(foo const&);   // Implement it in the most natural way 

    void swap(some_struct&) throw(); // Implement it in the most efficient way 

    // Google "copy and swap idiom" for this one 
    some_struct& operator=(some_struct x) { x.swap(*this); return *this; } 

    // Same idea 
    some_struct& operator=(foo const& x) 
    { 
     some_struct tmp(x); 
     tmp.swap(*this); 
     return *this; 
    } 
}; 

La mise en œuvre des choses de cette façon est la preuve imbécile, et est le meilleur que vous pouvez obtenir en terme de sémantique de conversion en C++, il est donc le chemin à parcourir ici.

Questions connexes