2010-10-14 19 views
4

En C++, est-il possible d'appeler une fonction d'une instance avant la fin du constructeur de cette instance?C++: Est-il possible d'appeler la fonction d'un objet avant la fin du constructeur?

par exemple. si le constructeur de A instancie le constructeur de B et B, il appelle l'une des fonctions de A.

+1

Tout est possible. La météo est valide ou même une bonne idée dépend de ce que vous faites. Plus de détails sur la relation A/B et ce que fait la méthode serait bien. (c'est-à-dire du code). –

+0

@ Martin, j'ai gardé la question générique volontairement. Dans mon cas particulier, les détails sont fastidieux et sans importance. En fait, après avoir lu les réponses, j'ai décidé de l'éviter, et de découpler le processus d'initialisation de la logique "go", qui lance la logique métier. Rétrospectivement, c'est une bonne pratique que je vais adopter. – Jonathan

+0

Bonne idée: Parce que les questions génériques vous donnent de bonnes réponses explicites? –

Répondre

11

Oui, cela est possible. Cependant, vous êtes responsable que la fonction invoquée n'essaiera pas d'accéder à des sous-objets dont le constructeur n'a pas été appelé. Habituellement, c'est très sujet aux erreurs, c'est pourquoi il devrait être évité.

+3

Inclus (mais qui mérite d'être souligné) est que vous ne devriez pas appeler les fonctions membres virtuels de votre constructeur, au moins, non sans comprendre ce qui se passera.Comme toute classe dérivée n'a pas encore été entièrement construite, l'appel d'une fonction virtuelle surchargée dans un constructeur de classe de base appellera l'implémentation de base de cette fonction (et si la fonction de classe de base est purement virtuelle, vous obtiendrez une erreur d'exécution). Donc, mieux vaut ne pas appeler _any_ fonctions virtuelles dans le constructeur. – Gretchen

+0

@Matthew: En effet. Merci pour cette précieuse addition! – sbi

4

Ceci est très possible

class A; 
class B { 
public: 
    B(A* pValue); 
}; 

class A { 
public: 
    A() { 
    B value(this); 
    } 
    void SomeMethod() {} 
}; 

B::B(A* pValue) { 
    pValue->SomeMethod(); 
} 
1

C'est possible et parfois pratiquement nécessaire (bien qu'il amplifie la possibilité de niveler un bloc de ville par inadvertance). Par exemple, en C++ 98, au lieu de définir une classe de base artificielle pour l'initialisation commune, en C++ 98, on voit souvent que cela est fait par une fonction init appelée par chaque constructeur. Je ne parle pas de la construction en deux phases, qui est juste du mal, mais de la prise en compte d'une initialisation commune.

C++ 0x fournit un transfert de constructeur qui aidera à résoudre le problème. Pour la pratique, il est dangereux, il faut être très prudent sur ce qui est initialisé et non. Et pour le purement formel, il y a une formulation inutilement vague dans la norme qui peut être interprétée comme si l'objet n'existait pas réellement jusqu'à ce qu'un constructeur se soit terminé avec succès. Cependant, étant donné que cette interprétation lui ferait utiliser UB par ex. une fonction init pour exclure l'initialisation commune, ce qui est une pratique courante, il peut juste être ignoré.

Vive & HTH.,

-2

pourquoi voudrais-tu faire ça? Non, cela ne peut pas être fait car vous devez avoir un objet comme l'un de ses paramètres. L'implémentation de la fonction membre C++ et la fonction C sont des choses différentes.

C++ Code

class foo 
{ 
    int data; 
    void DoSomething() 
    { 
     data++; 
    } 
}; 


int main() 
{ 
    foo a;    //an object 
    a.data = 0;   //set the data member to 0 
    a.DoSomething(); //the object is doing something with itself and is using 'data' 
} 

Voici une façon simple comment faire C.

typedef void (*pDoSomething)(); 
typedef struct __foo 
{ 
    int data; 
    pDoSomething ds; //<--pointer to DoSomething function 
}foo; 

void DoSomething(foo* this) 
{ 
    this->data++; //<-- C++ compiler won't compile this as C++ compiler uses 'this' as one of its keywords. 
} 

int main() 
{ 
    foo a; 
    a.ds = DoSomething; // you have to set the function. 
    a.data = 0; 
    a.ds(&a);  //this is the same as C++ a.DoSomething code above. 
} 

Enfin, la réponse à votre question est le code ci-dessous.

void DoSomething(foo* this); 
int main() 
{ 
    DoSomething(??); //WHAT!?? We need to pass something here. 
} 

Vous voyez, vous avez besoin d'un objet pour passer. La réponse est non.

+1

Vous venez presque trois heures après que Jared a montré comment cela pourrait arriver et dans votre deuxième phrase vous vous dites que ça ne peut pas être fait ?! Je suis étonné. – sbi