2010-09-21 3 views
3

Je le code ci-dessous:C++ confusion virtuelle inheritace et transtypage/constructeur copie

class A 
{ 
}; 

class B: public virtual A 
{ 
public: 
    B() 
    { 
     cerr << "B()"; 
    } 
    B(const A& a) 
    { 
     cerr << "B(const A&)"; 
    } 
}; 

class C: public B 
{ 

}; 

int main(int argc, char **argv) 
{ 
    B *b = new B(C()); 
} 

À ma grande surprise B (const A & a) n'est pas appelé. Pourquoi donc?

+0

Cela n'a rien à voir avec le fait que l'héritage virtuel est utilisé; l'héritage non virtuel présenterait le même comportement. –

Répondre

8

B dispose également d'un constructeur de copie implicitement déclaré est déclarée comme

B(const B&); 

Cette fonction membre implicitement déclarée est appelé parce qu'il est un meilleur match pour l'argument de type C que votre constructeur a déclaré l'utilisateur, B(const A&) .

1

C'est ce que je suis quand j'ai essayé clang++ -cc1 -ast-dump sur votre code

class B : virtual public A { 
    class B; 
public: 
    B() : A() (CompoundStmt 0xb85950 <a.cpp:9:5, line:11:5>) 


    B(A const &a) : A() (CompoundStmt 0xb859c0 <a.cpp:13:5, line:15:5>) 


    inline B &operator=(B const &) throw(); 
    inline void ~B() throw(); 
    inline B(B const &) throw() : A((ImplicitCastExpr 0xb86a10 <a.cpp:5:7> 'clas 
s A const' <UncheckedDerivedToBase (virtual A)> lvalue 
    (DeclRefExpr 0xb869ec <col:7> 'class B const' ParmVar='' 0xb86170)) 
) (CompoundStmt 0xb86ab0 <a.cpp:5:7>) 

Comme vous pouvez voir votre classe B a un (synthétisé compilateur) implicitement déclaré copie cteur.

inline B(B const &) throw(): qui est une meilleure correspondance pour le type C argument comme James McNellis dit dans his answer. C'est pourquoi vous ne voyez pas un appel à B(const A& a) car il ne se fait jamais appeler réellement.