2012-05-15 1 views
0

J'ai des problèmes avec les fonctions amis en C++, mais je soupçonne que c'est plus un symptôme d'un problème que j'ai avec les directives du préprocesseur et #include.problèmes de fonction ami

Ceci est un exemple stupide de ce que je faisais. Cinq fichiers: bobby.h, bobby.cpp, billy.h, billy.cpp et main.cpp. Billy a une fonction protégée appelée ReceiveMoney. Bobby a une fonction appelée banque qui appelle Billy's ReceiveMoney. c'est-à-dire qu'à chaque fois que Bobby se rend à la banque, il partage l'argent avec Billy.

billy.h

#ifndef BILLY_H 
#define BILLY_H 
#include "bobby.h" 

class Billy 
{ 
friend void Bobby::Bank(int, Billy &); 
public: 
    Billy(); 
protected: 
    void ReceiveMoney(int inc); 
private: 
    int money; 
}; 
#endif 

billy.cpp

#include "billy.h" 

Billy::Billy() 
{ 
    money = 0; 
} 

void Billy::ReceiveMoney(int inc) 
{ 
    money+=inc; 
} 

bobby.h

#ifndef BOBBY_H 
#define BOBBY_H 

#include "billy.h" 

class Bobby 
{ 
public: 
    Bobby(); 
    void Bank(int amount, Billy & b); 
protected: 
    int money; 
}; 
#endif 

bobby.cpp

#include "bobby.h" 

Bobby::Bobby() 
{ 
    money = 0; 
} 
void Bobby::Bank(int amount, Billy & b) 
{ 
    b.ReceiveMoney(amount/2); 
} 

main.cpp

#include "billy.h" 
#include "bobby.h" 

int main() 
{ 
    Bobby bo; 
    Billy bi; 
    bo.Bank(150, bi); 
    return 0; 
} 

Je reçois un grand nombre d'erreurs, généralement erreur C2653: « Bobby »: n'est pas un nom de classe ou espace de noms ou erreur C2653: « Billy »: n'est pas une classe ou nom de l'espace de noms

Je fais cela dans un projet de console vide dans VS0

Répondre

3

Vous avez une dépendance circulaire des fichiers d'en-tête.
billy.h inclut bobby.h, tandis que bobby.h inclut billy.h.
De toute évidence, le compilateur ne peut pas distinguer les types en raison de cette dépendance circulaire.

La meilleure solution est de repenser votre conception et éviter la dépendance circulaire ou
Utilisez Forward declarations pour briser la dépendance circulaire.

Juste avant de déclarer la classe Billy dans bobby.h

//#include "billy.h"  <----- You don't need this include 
class Billy;    <----- Just Forward Declaration should suffice 

Vous pouvez utiliser une déclaration avant ici parce que, Déclaration des fonctions ou des méthodes qui accepte/retour types incomplets, dans ce cas Billy est un type incomplet pour le compilateur.

+0

Eh bien, je ne suis pas complètement nouveau à ce sujet. J'ai essayé d'avancer des déclarations. La ligne b.ReceiveMoney (montant/2); dans bobby.cpp provoque une erreur pour l'utilisation du type non défini 'Billy' – Tim

+0

@Tim: Inclure 'billy.h' dans' bobby.cpp'. –

+0

Merci, vous avez été très utile. – Tim

1

Il y a une boucle dans votre #include, vous ne pouvez pas faire cela. Vous devez utiliser une déclaration forward de Bobby dans billy.h. Tels que class Bobby;. Vous ne serez pas en mesure de déclarer la fonction ami même avec cela.

La seule vraie solution est d'éviter la nécessité d'un friend. ReceiveMoney devrait être public en fait: si Bobby représente quelque chose comme un compte, c'est logique.

Les contraintes sur friend le rendent utile uniquement pour résoudre le comportement interne des classes (par exemple avec les collections et les nœuds qui les implémentent).

+0

Ce que je voulais, c'était avoir une fonction utilisable seulement par une certaine classe et seulement dans une certaine fonction de cette classe. Je ne peux pas imaginer qu'il n'y a pas moyen de le faire. – Tim

+0

Je comprends ce que vous essayez de faire, mais dans OO, vous faites généralement l'inverse: vous rendez public ce qui doit être appelé d'autres classes et vous créez une interface dont Billy dérivera, que vous fournissez réellement aux "clients" de votre code. L'interface ne contient pas ReceiveMoney dans votre cas. – armel

0

En raison de la dépendance circulaire, aucune des classes n'est entièrement définie. d'où le grand nombre d'erreurs. Si possible, changez votre conception et héritez ou incluez seulement les choses nécessaires. Comme mentionné par Als déclarations à l'avance peut être un choix. Les dépendances circulaires sont principalement dues à des défauts de conception.