2014-09-18 3 views
0

donc mon problème n'est pas tant sur le code, mais sur la façon de le faire. Je travaille sur une interface graphique et je veux que mes boutons sachent qui est le parent. Et bien sûr, la fenêtre sait quels boutons elle a.Comment résoudre une dépendance circulaire spécifique?

Cela crée une dépendance circulaire, car les deux doivent pouvoir accéder aux autres méthodes et attributs, du moins c'est ce que je préfère.

J'ai trouvé une solution qui fonctionne, mais je ne suis pas très content:

J'ai créé un troisième objet auquel bouton écrit, ce qu'il veut la fenêtre faire. Et la fenêtre vérifie ce troisième objet pour les commandes.

Je voulais vous demander, si vous connaissez un meilleur moyen pour cela, puisque je ne pouvais pas trouver d'autre moyen, cela fonctionne pour moi.

Merci!

+0

Pourquoi vous voulez éviter circulaires dépendances? – GingerPlusPlus

+0

@GingerPlusPlus Parce que les dépendances circulaires sont un signe de mauvaise conception. –

+0

@GingerPlusPlus parce que vous ne pouvez pas compiler du code qui a des dépendances circulaires, et si vous les avez en premier lieu, votre code n'est pas correctement architecturé. – CoryKramer

Répondre

1

Je suggère de créer une interface de fenêtre. Fournir un pointeur arrière à l'interface de la fenêtre dans le constructeur du bouton. La fenêtre qui possède le bouton dépend du bouton et le bouton dépend de l'interface de la fenêtre. Aucune dépendance circulaire.

struct IWindow { 
}; 

struct Button { 
IWindow* window_; 
Button(IWindow* window) : window_(window){} 
}; 

struct WindowWithButton : IWindow { 
    Button button_; 
    WindowWithButton() : button_(this) {} 
}; 

ajouter ensuite des méthodes virtuelles à IWindow qui sont mis en œuvre par WindowWithButton afin que Button peut obtenir les informations dont il a besoin de la WindowWithButton.

+0

Merci beaucoup! C'est beaucoup plus agréable que ce que j'ai trouvé. – LordOfThunder123

0

Il est un modèle standard:

struct Window; // Forward-declare the parent 
struct Button { 
    void pingParent(); // Only declare members which need 
     // more than superficial knowledge of Window 
    Window* parent; // Ok, we know there is a Window, somewhere 
}; 
struct Window { 
    unique_ptr<Button> child; 
    // Other functions using the button 
    void pingpong() {child->pingParent();} 
    void ping(){} 
}; 
/*optional inline*/ void Button::pingParent() { 
    parent->ping(); 
} 
+0

Merci à vous aussi. Votre solution fonctionnerait aussi bien. Mais quand je travaille avec includes, n'aurais-je pas besoin de définir le pingParent() réel dans le Window.h/Window.cpp? Cela ne rend-il pas le code assez confus? – LordOfThunder123

+0

Vous le définissez dans un en-tête de sorte que chaque TU qui l'appelle possède la définition.Si vous n'utilisez pas 'inline', cela doit être dans exactement un fichier d'implémentation, pas dans un en-tête. J'éviterais les interfaces (avec des fonctions virtuelles pour le dépassement) à moins que cela ne soit nécessaire, car il y a une performance et une pénalité d'espace associée à leur utilisation. – Deduplicator

Questions connexes