2012-08-31 1 views
0

J'ai une classe de modèle appelé Variable, avec un constructeur spécialisé pour char *, qui est défini comme suit:Modèle de modèle-type de données

template<> 
Variable<char*>::Variable(char * const &arg_value) 
{ 
    value = new char[strlen(arg_value) + 1]; 
    strncpy(value, arg_value, strlen(arg_value)); 
    value[strlen(arg_value)] = '\0'; 
} 

Maintenant, j'ai cette déclaration, qui déclare un Variable<char*>:

Variable<char*> stringVar = const_cast<char*>("Hi");

Dans ma définition Variable, je ne ai jamais déclaré ou défini un constructeur de copie à un const char *. Cependant, la déclaration fonctionne parfaitement bien. Pourquoi est-ce? Je suis assez positif que stringVar a un type de données de Variable<char*>, mais cela fonctionne toujours. D'où vient cette mission?

+2

Un signe égal dans la déclaration n'est pas une affectation. – chris

+0

Est-ce le constructeur de la copie? – ZERO

+2

'Variable' n'est pas une classe de modèle. C'est un * template de classe *. –

Répondre

4

Un constructeur qui prend un argument permet conversions implicites. Voici un exemple plus simple de votre situation:

struct Foo { Foo(int, double = 0.5, char = 'a') { } }; 

void bar(Foo); 

Foo x = 1; // OK! 
bar(2); // also OK 

Pour inhiber cette conversion implicite, dire explicit:

struct Eew { explicit Eew(int) { } }; 

// Eew e = 3; // error 
Eew e2 = Eew(3); // OK but weird 
Eew e3(3);  // correct 
2
Variable<char*> stringVar = const_cast<char*>("Hi"); 

appelez implicitement le c-tor de la classe Variable<char*>. Il est égal à

Variable<char*> stringVar = Variable<char*>(const_cast<char*>("Hi")); 
+0

Oh, donc lors de l'assignation de data-type1 à data-type2, C++ cherchera dans les constructeurs de data-type1 pour voir si l'un d'entre eux accepte char * const comme paramètre ? Est-ce pour tous les types de données? – ZERO

+0

@ZERO ce n'est pas assigner. C'est l'initialisation. – ForEveR

1

Vous invoquer le constructeur de copie par défaut. Déclarez-en un caché dans votre modèle Variable <> et regardez la pause de la compilation.

+0

Est-ce que le constructeur de copie n'est pas seulement pour copier la même classe? – ZERO

+0

Oui, mais vous expérimentez ce que l'on appelle une construction implicite du côté droit. Traçant dans un débogueur, vous trouverez que vous construisez deux objets; pas une. Il y a longtemps que j'ai sauté dans la construction quand-est-implicite-prévue contre pas. Cependant dans votre cas, je crois que le RH de l'assignation construit implicitement une Variable puisqu'un constructeur défini peut réaliser le type de données, puis en envoyant le constructeur de copie par défaut pour le vider dans vos lhs au moment de sa construction. – WhozCraig

1
char hi[] = "Hi"; 
Variable<char*> stringVar = hi; 

La deuxième ligne ci-dessus est sémantiquement équivalent à:

Variable<char*> stringVar(implicit_cast<Variable<char*>>(hi)); 

En supposant qu'il y avait un tel chose comme implicit_cast qui a effectué une conversion de type au type de destination si et seulement s'il y a une conversion implicite disponible. Dans votre cas, le constructeur:

Variable<T>::Variable(T const &) 

prévoit la conversion implicite: Variable<char*>::Variable(char * const &) peut être utilisé pour convertir char*-Variable<char*>.

Notez que si sémantiquement c'est ce qui se passe, en réalité, la copie sera éludée et le code sera compilé à l'équivalent:

Variable<char*> stringVar(hi); 

C'est, après que tous les contrôles ont été effectués: une conversion implicite De hi au type est disponible, et le constructeur de copie peut être appelé implicitement.