2009-07-07 9 views
1

Serait-il correct de dire que chaque fois que le moulage est utilisé, l'objet résultant est un objet const ?coulée produisant des objets const en C++

... Et ne peut donc être utilisé comme argument que si cette fonction l'accepte comme un objet const?

par exemple.

class C1 { 
    public: C1(int i=7, double d = 2.5){}; 
}; 

void f(C1& c) {}; 

int main(){ 
    f(8); 
    return 1; 
} 
//won't compile 

(Bien sûr, si f (....) reçoit l'argument en valeur il obtient une version non-const qu'elle peut travailler avec)

Répondre

12

Habituellement, quand un objet d'un certain type est converti en un objet d'un autre type (un type sans référence), un objet temporaire est créé (pas un objet const). Un objet temporaire (invisible, sans nom, rvalue) ne peut que lier (en C++ 98/03) des références const (à l'exception du temporaire connu sous le nom d'objet d'exception). Par conséquent, le résultat d'une conversion qui crée un temporaire ne peut être utilisé qu'en tant qu'argument d'une fonction qui l'accepte en tant que référence const ou en tant que type dans lequel elle peut être copiée/convertie.

Par exemple, par exemple.

void f(double); // 1 
void f(const int&); // 2 
void f(int&); // 3 

struct B { B(int) { } }; 
struct C { C(int) { } }; 
void f(B b); // 4 
void f(B& b); // 5 
void f(const C& c); //6 
void f(C& c); // 7 

// D inherits from B 
struct D : B { D(int) : B(0) { } }; 
void f(D& d); // 8 

int main() 
{ 
    f((int) 3.0); // calls 2, NOT 3 
    f((float) 3); // calls 1 - const reference requires the same type 
    f(1); // calls 2, NOT 3 

    f((B) 1); // calls 4, not 5 - can accept it by non-const value 
    f((C) 1); // calls 6, not 7 - can accept it by const-reference 

    f((D) 1); // calls 4, not 8 - since a 'D' temporary object can be converted to a 'B' object - but will not bind to a non-const reference 
} 

Espérons que ça aide.

+1

+1: J'aime cette réponse. Il peut être utile de donner les rangs et les types de chaque conversion (pour montrer pourquoi une version particulière est sélectionnée par rapport à une autre). S'il vous plaît vérifier que j'ai raison. J'énumère A, B, C, .... - Premier appel (A): correspondance exacte à 2, conversion en 1. (B) promotion en 1, conversion en 2. (C) correspondance exacte en 2, conversion en 1. (D) correspondance exacte à 4. (E) correspondance exacte à 6. (F) Conversion (dérivée-> base) à 4. - Dans toutes les liaisons de référence de 'const T &' à rvalue 'T', le 'const T' est considéré comme un const de niveau supérieur, et n'affecte pas le rang (' void f (T); void f (const T &); f (T()); 'ambiguë) –

+0

oui je pense que vous êtes juste dans votre décomposition des conversions et le classement - puisque nous avons couvert OU ici http://stackoverflow.com/questions/1092714/conversion-precedence-in-c/1092724#1092724, je ne voulais pas trop se concentrer sur Résolution de surcharge - mais plus encore à quoi un temporaire pourrait se lier - peut-être aurais-je dû utiliser différents noms de fonctions et le garder plus simple? –

+0

Oh je vois. Je ne sais pas ce qui serait mieux. Mais j'aime bien comment c'est actuellement.Les gens pourraient lire votre autre réponse et regarder dans la section des commentaires s'ils veulent savoir pourquoi une version est préférée en particulier. –

0

Vous pouvez réécrire que:

class C1 
{ 
    public: C1(int i=7, double d = 2.5){}; 

}; 

void f(C1& c){}; 

int main() 
{ 
    C1 c(8); //named 
    f(c); 
    //... can access the modified C1 instance here ... 
    return 1; 
} 

La seule chose que le compilateur n'aime pas votre version est que votre C1 instance est un non nommé temporaire: qui f modifiera, mais (parce qu'il est un non-nommé temporaire) le compilateur sait que l'appelant (main) n'a aucun moyen de recevoir/conserver/noter ces modifications.

3

Il est un peu loin d'appeler ce 'casting'. Vous faites une «construction implicite». La construction implicite crée toujours un objet temporaire, qui à son tour est toujours const. Notez que vous pouvez marquer le constructeur 'explicite' et cela bloquerait l'appel de construction implicite que vous voyez ici. Mais cela signifie seulement que vous auriez besoin de f (C (8)) au lieu de f (8); l'instance C serait toujours const car elle est temporaire, mais notez qu'aucune distribution n'est en cours.

Voir aussi const_cast pour les solutions de contournement sales si vous avez vraiment, vraiment besoin de. L'autre solution serait de faire un doublure: C c (8); f (c);