2010-04-15 8 views
2

J'écris une classe, et ce doute est apparu. Est-ce undef. comportement? D'un autre côté, je ne suis pas sûr que ce soit recommandé, ou si c'est une bonne pratique. Est-ce un si je n'assure aucune exception à lancer dans la fonction init?Appel d'une fonction non membre sur une instance avant que soit construit

//c.h 
class C{ 

    float vx,vy; 
    friend void init(C& c); 
public: 
    C(); 

}; 


//c.cpp 
C::C() 
{ 
    init(*this); 
} 

void init(C& c) //throws() to ensure no exceptions ? 
{ 
    c.vx = 0; 
    c.vy = 0; 
} 

Merci à l'avance

+0

Vous n'a pas fourni un corps pour vous dtor. Il suffit de le supprimer. –

+0

@epronk. Son code d'exemple, mais ok, laisse être correct. – Tom

+0

'throw()' ne garantit pas qu'il n'y aura aucune exception, il ajoute une vérification de l'exécution qui appellera 'terminate' (ou l'une des autres gorgones) si jamais une exception passe. Il n'y a malheureusement pas de vérification à la compilation des spécifications d'exception ... La prochaine norme ajoutera le mot-clé 'noexcept', pour préciser qu'une méthode ne sera jamais lancée, mais c'est au programmeur de l'assurer et si jamais il vous lance dans le royaume terrible de comportement indéfini. –

Répondre

6

Il est tout à fait bien. Une fois que vous entrez dans le corps du constructeur, tous les membres ont été initialisés et ils sont prêts à être utilisés. (Le corps est alors de finir tout autre travail qui doit être fait pour créer un objet entièrement construit.)

Mais c'est un style pauvre. Mieux vaut juste:

C::C() : 
vx(), vy() // or vx(0), vy(0) if you prefer to be explicit 
{} 

Et faites disparaître tout le désordre.


Les exceptions n'ont rien à voir avec la sécurité, les constructeurs sont libres de lancer. En fait, si vous ne parvenez pas à construire un objet, le lancement d'une exception est le mode d'action préféré.

+0

Merci, la partie exception a dégagé quelques doutes. Est-ce correct de le faire class C {float vx(); float vy(); public: ...} ;? – Tom

+0

... signifiant "et ainsi de suite", pas une utilisation incorrecte de varargs. – Tom

+0

@Tom: C'est * OK * mais pas ce que vous voulez. (Indice: cela me ressemble :) :) Malheureusement, il n'y a pas de façon simple de dire "hé, fais ce zéro donc je n'ai pas besoin d'écrire un constructeur". – GManNickG

0

Au moment où le contrôle atteint le constructeur, toutes les variables auraient des valeurs par défaut.

+0

Eh, un agrégat ne reçoit aucune initialisation, sa valeur est indéterminée. – GManNickG

0

Je peux penser à un cas spécifique où cela pourrait vous mordre. Si C est destiné à être une classe de base, permettre une référence à celui-ci pour échapper à des fonctions non-membres peut provoquer une surprise. Dans le cas de la classe de base, les constructeurs sont plus spéciaux car la classe dérivée n'a pas encore été construite et les fonctions virtuelles appellent la classe de base plutôt que la classe dérivée. Les fonctions non membres ne peuvent pas s'attendre à obtenir un objet dans cet état, et parce qu'ils ne ressemblent pas à des constructeurs, il serait facile d'introduire des bogues en l'oubliant.

Il comportement est toujours pas définie si - comportement surprenant :) juste défini