2010-06-11 8 views
0

Voici mon extrait de code:Constructor surcharge problème en C++ Héritage

class Request 
{ 
public: 
Request(void); 
……….. 
} 

Request::Request(void) 
{ 
qDebug()<<"Request: "<<"Hello World"; 
} 


class LoginRequest :public Request 
{ 
public: 
LoginRequest(void); 
LoginRequest(QDomDocument); 
…………… 
} 

LoginRequest::LoginRequest(void) 
{ 
qDebug()<<"LoginRequest: "<<"Hello World"; 
requestType=LOGIN; 
requestId=-1; 
} 

LoginRequest::LoginRequest(QDomDocument doc){ 
qDebug()<<"LoginRequest: "<<"Hello World with QDomDocument"; 
LoginRequest::LoginRequest();  
xmlDoc_=doc;   
} 

Lorsque le constructeur d'appel de Overrided LoginRequest

LoginRequest *test=new LoginRequest(doc); 

je suis venu avec ce résultat:

Request: Hello World 
LoginRequest: Hello World with QDomDocument 
Request: Hello World 
LoginRequest: Hello World 

Il est évident que les deux constructeur de LoginRequest appelé constructeur REquest.

Y a-t-il un moyen d'éviter cette situation?

Je peux construire une autre fonction qui fait le travail que je veux faire et que les deux constructeurs appellent cette fonction. Mais je me demande s'il y a une solution?

Edit: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.3

+0

Pourquoi voudriez-vous faire face à cette situation? Vous créez deux 'LoginRequest's. Évidemment, cela signifie que vous avez 2 demandes, et le ctor de demande devrait être appelé deux fois. – MSalters

+0

En fait, je voulais créer un LoginRequest, mais maintenant je vois ma faute. – metdos

Répondre

6

Le code ne fait pas ce que vous pensez probablement faire. La ligne:

LoginRequest::LoginRequest();  

construit un objet temporaire qui est immédiatement détruit. Comme d'autres l'ont suggéré, vous pouvez mettre du code en double dans une fonction privée, mais cela pose beaucoup de problèmes - en particulier, une telle fonction ne peut effectuer que l'assignation, et de nombreuses classes ne supportent pas l'affectation. Une solution un peu mieux est de mettre en œuvre un seul constructeur avec un argument par défaut:

class LoginRequest { 
    .... 
    LoginRequest(QDomDocument d = DefaultDoc()); 
}; 
+0

Pourquoi ne peut-il pas s'initialiser? – metdos

+0

@metdos Parce qu'il est appelé (vraisemblablement) après l'initialisation. Je ne comprends pas ton deuxième commentaire. –

+0

@metdos Désolé - ne comprends toujours pas. C'est une variable, vous l'utilisez comme si vous utilisiez d'autres variables. –

2

Oui, est un bon (oder peut-être mieux: faire une hiérarchie de classes Demande - de LoginRequest - de LoginRequestWithDoc) votre solution pour utiliser une fonction et appeler des deux constructeurs. C# fournit ce que vous avez besoin/essayé d'atteindre mais pas C++: un ctor d'une classe appelle un autre ctor de la même classe.

class LoginRequest 
{ 
    public LoginRequest() 
    { 
    // ... 
    } 

    public LoginRequest(Document doc) 
    : this() // <<< order of execution: Request() -> LoginRequest() 
       //       -> LoginRequest(doc) 
    { 
    // ... 
    } 
} 
+0

Bien qu'il sera en C++ 0x. –

1

je peux construire une autre fonction qui fait le travail que je veux faire et avoir les deux constructeurs appellent cette fonction. Mais je me demande s'il y a une solution?

Oui, il y a:

D'abord, déplacer le code d'initialisation dans une liste d'initialisation. C'est une pratique de codage plus efficace et plus efficace. Deuxièmement, tout code qui est commun aux deux constructeurs et non une initialisation (c'est-à-dire qu'il ne peut pas être placé dans une liste d'initialisation) doit être déplacé vers une fonction privée commune et appelé par les deux constructeurs.

Habituellement, il n'est pas bon d'appeler un constructeur d'un autre constructeur car - selon ce que fait le compilateur vous pourriez avoir un comportement étrange/indéfini (dans ce cas la classe de base est initialisée deux fois).

+1

Non, la classe de base n'est pas initialisée deux fois. Une instance de classe de base complètement différente est créée. –