2010-03-15 3 views
3

Pourquoi le constructeur du convertisseur de la classe Child est-il appelé dans le code ci-dessous? Je veux dire, il convertit automatiquement la base en enfant via le constructeur du convertisseur enfant. Le code ci-dessous compile, mais ne devrait-il pas pas compiler puisque je n'ai pas fourni bool Child::operator!=(Base const&)?C++ Pourquoi le constructeur du convertisseur est-il implicitement appelé?

class Base 
{ 
}; 

class Child : public Base 
{ 
public: 
    Child() {} 
    Child(Base const& base_) : 
    Base(base_) 
    { 
    std::cout <<"should never called!"; 
    } 
    bool operator!=(Child const&) 
    { 
    return true; 
    } 
}; 

void main() 
{ 
    Base base; 
    Child child; 

    if(child != base) 
    std::cout << "not equal"; 
    else 
    std::cout << "equal"; 
} 
+0

Je suppose que ce post pourrait être un bon exemple de la raison pour laquelle le mot clé explicite existe. – sivabudh

+0

Devrais-je renommer le titre du constructeur de copie en constructeur de convertisseur? – sivabudh

Répondre

3

Parce que vous avez fourni un constructeur de conversion. Si vous ne voulez pas le compilateur pour convertir automatiquement Base objets à l'aide de la Child

Child(Base const& base_) 
constructeur

, rendre explicite:

explicit Child(Base const& base_) 

De cette façon, le constructeur ne sera appelée lorsque vous spécifiez explicitement il, dans des contextes tels que:

Child ch(base); 
foo(Child(base)); 
new Child(base); 
+1

Merci. Maintenant, je comprends les besoins pour un mot-clé explicite. – sivabudh

0

Parce que vous ne fournissez aucun opérateur =() qui prennent comme argument de base: le compilateur va essayer « w Il peut "et voir qu'il existe un constructeur de conversion au type d'argument (Child) qui peut être appelé. Donc il l'utilise pour faire le! = Travail.

1

Parce que l'enfant ne peut pas être comparé à la base - il ne peut être comparé à un autre enfant. Ainsi, votre compilateur crée une copie implicite de Base to Child afin de provoquer la conversion. Si vous modifiez votre code à:

class Child : public Base 
{ 
public: 
    Child() {} 
    explicit Child(Base const& base_) : 
    Base(base_) 
    { 
    std::cout <<"should never called!"; 
    } 
    bool operator!=(Child const&) 
    { 
    return true; 
    } 
}; 

Vous constaterez qu'il ne compile plus.

6

La fonction avec la signature Child(Base const& base_) n'est pas un constructeur de copie (le type de droite n'est pas le même que celui de gauche). Ce constructeur peut être utilisé implicitement par le compilateur pour contraindre un type dans un autre dans le but de la comparaison que vous faites dans main. Pour éviter cela, marquez le constructeur explicit.

Questions connexes