2010-09-17 3 views
3

J'ai un problème lors de la création d'une forme de hiérarchie avec différents types d'objet. J'ai une classe qui a un membre d'une autre classe, comme ceci:Résolution du référencement croisé

class A 
{ 
public: 
    A(){} 
    ~A(){} 

    void addB(B* dep){ 
     child = dep; 
     dep->addOwner(this); 
    } 
    void updateChild(){ 
     child->printOwner(); 
    } 
    void print(){ 
     printf("Printing..."); 
    } 
private: 
    B* child; 
}; 

Et c'est la classe B:

class B 
{ 
public: 
    void addOwner(A* owner){ 
     ownerObject = owner; 
    } 

    //ISNT WORKING 
    void printOwner(){ 
     ownerObject->print(); 
    } 

private: 
    A* ownerObject; 
}; 

Appel d'une fonction de « B » hors de la classe « A » fonctionne seulement bien mais l'essayer vice versa donne une erreur de compilateur car A n'est pas défini dans B. C'est en fait en utilisant une déclaration include et une forward, mais je suppose que c'est un problème de référence que le compilateur ne peut pas résoudre.

Y at-il une chance de résoudre ce problème ou devrais-je repenser mon design?

Répondre

8

Vous dites que vous avez déjà résolu votre problème de dépendance circulaire en utilisant une déclaration avant de A au lieu d'inclure l'en-tête où A est défini, donc vous savez déjà comment éviter les inclusions circulaires. Toutefois, vous devez connaître what is possible and what is not with incomplete types (c'est-à-dire les types qui ont été déclarés en avant).

Dans votre cas, vous essayez d'appeler la fonction membre print sur un objet qui a un type incomplet; le compilateur ne sait rien de ce type, sauf qu'il sera défini à un moment donné, il ne vous permet donc pas de le faire. La solution est de supprimer la mise en œuvre de la fonction de membre printOwner de l'en-tête B et le mettre dans un fichier de mise en œuvre:

//B.hpp 

class A; // forward declaration 

class B 
{ 
    public: 
    void addOwner(A* owner); 

    void printOwner() const; // I think this member function could be const 

    private: 
    A* ownerObject; 
}; 

//B.cpp 

#include "B.hpp" 
#include "A.hpp" // here we "import" the definition of A 

void B::addOwner(A * owner) 
{ 
    ownerObject = owner; 
} 

void B::printOwner() const 
{ 
    ownerObject->print(); //A is complete now, so we can use its member functions 
} 

Vous pourriez peut-être faire la même chose dans l'en-tête A.

2

Vous devriez probablement repenser votre conception, car une relation parent-enfant cruelle est généralement une odeur de code.

Mais, vous pouvez faire le compilateur heureux:

#include <cstdlib> 
#include <cstdio> 

class A 
{ 
public: 
    A(){} 
    ~A(){} 

    void addB(class B* dep); 
    void updateChild(); 
    void print(){ 
     printf("Printing..."); 
    } 
private: 
    class B* child; 
}; 

class B 
{ 
public: 
    void addOwner(A* owner){ 
     ownerObject = owner; 
    } 

    //ISNT WORKING 
    void printOwner(){ 
     ownerObject->print(); 
    } 

private: 
    A* ownerObject; 
}; 

void A::addB(class B* dep){ 
    child = dep; 
    dep->addOwner(this); 
} 

void A::updateChild(){ 
    child->printOwner(); 
} 



int main() 
{ 
    return 0; 
} 
+0

Merci beaucoup! La véritable idée derrière ce "design" était d'avoir une classe (dans cet exemple A) qui fonctionne comme un conteneur pour beaucoup de classes abstraites ("B"), de sorte que tous les "B" étendant la fonctionnalité de "A "en fonction de leur mise en œuvre concrète. Pour la fonctionnalité qui est la même pour tous les objets B, je crée une implémentation dans A, car il n'aurait pas de sens d'avoir 10 objets B ayant des fonctionnalités identiques. Au moins, ce serait aussi un problème de synchronisation. – SideEffect

+0

@ user450556: J'ai l'impression que vous voudrez peut-être vous pencher sur la conception basée sur des politiques –

0

Vous devez déplacer B :: printOwner mise en œuvre dans le fichier .cpp.

2

Vous pouvez utiliser avant la déclaration et définir les fonctions membres en dehors de la classe, à savoir

// A.h 
class B; 
class A { public: 
    void addB(B* dep); // don't define addB here. 
    ... 
}; 

// B.h 
class A; 
class B { public: 
    void addOwner(A* owner); // don't define addOwner here. 
    ... 
}; 

// A.cpp 
#include "A.h" 
#include "B.h" 
void A::addB(B* dep) { 
    ... 
} 

// B.cpp 
// similar. 
Questions connexes