2009-10-30 5 views
1

Dire que je voulais avoir une variable dans une classe toujours dans une relation à l'autre sans changer explicitement la variable « liée ». Par exemple: int foo est toujours inférieur de 10 à la barre d'int.Way pour relier 2 variables dans une classe en C++

Faire en sorte que si je changeais bar, foo serait changé. Y a-t-il un moyen de faire cela? (Dépassement d'entier n'est pas vraiment possible donc ne vous inquiétez pas.)

Exemple: (ne fonctionne évidemment pas, mais le code général pour comprendre)

class A 
{ 
    int x; 
    int y = x - 10; // Whenever x is changed, y will become 10 less than x 
}; 
+0

Est-ce que C++ a une variable d'instanciation par référence comme en PHP? Vous pouvez instancier y pour avoir la référence à x-10, donc quand x change, x-10 change également en y. –

+0

Je suggère la solution de James pour utiliser une seule variable. Si vous ne pouvez pas le faire pour une raison quelconque, le contrôle d'accès (membres privés) vous aide à imposer cet invariant puisque personne en dehors de la classe ne peut jouer avec x et y. – sellibitze

Répondre

8

Non, vous ne pouvez pas fais ça. Votre meilleure option pour ce faire est d'utiliser les fonctions membres accesseurs et imitatrice:

int getFoo() 
{ 
    return foo_; 
} 

void setFoo(int newFoo) 
{ 
    foo_ = newFoo; 
} 

int getBar() 
{ 
    return foo_ + 10; 
} 

void setBar(int newBar) 
{ 
    foo_ = newBar - 10; 
} 
+0

Je ne veux pas le faire explicitement. – trikker

+0

C'est la seule façon de le faire ... – EToreo

+0

Ok, merci pour la réponse. Je suppose que je vais comprendre quelque chose. – trikker

3

Ceci est appelé un invariant. C'est une relation qui doit tenir, mais ne peut pas être appliquée par les moyens fournis par le langage de programmation. Les invariants ne devraient être introduits que lorsqu'ils sont vraiment nécessaires. D'une certaine manière, les choses sont relativement «mauvaises», car elles peuvent être brisées par inadvertance. Donc, la première question que vous devez vous poser est de savoir si vous devez vraiment introduire cet invariant. Peut-être que vous pouvez faire sans deux variables dans ce cas, et peut simplement générer la deuxième valeur à partir de la première variable à la volée, tout comme James suggéré dans sa réponse.

Mais si vous avez vraiment besoin de deux variables (et très souvent il n'y a pas moyen de contourner cela), vous vous retrouverez avec un invariant. Bien sûr, il est possible d'implémenter manuellement quelque chose en C++ qui relierait les variables ensemble et en changerait une quand l'autre changerait, mais la plupart du temps cela n'en vaut pas la peine. La meilleure chose que vous pouvez faire, si vous avez vraiment besoin de deux variables, encore une fois, est de faire attention à garder la relation nécessaire manuellement et utiliser beaucoup d'affirmations qui vérifierait l'invariant chaque fois qu'il peut casser (et parfois même quand il ne peut pas) , comme

assert(y == x - 10); 

dans votre cas. En outre, certaines bibliothèques C++ tierces avancées (telles que Boost, par exemple) pourraient fournir des outils d'assertion de haut niveau pouvant être programmés pour surveiller les invariants dans le code (je ne peux pas suggérer n'importe quoi), c.-à-d. que vous pouvez faire fonctionner la langue pour vous ici, mais cela doit être une solution de bibliothèque. Le langage de base ne vous aidera pas ici.

+0

+1 Mais je pense que vous devriez ajouter quelque chose à propos des classes et des membres privés à votre réponse. Le contrôle d'accès aide à renforcer les invariants. – sellibitze

2

Vous pouvez créer une nouvelle structure qui contient les deux variables et surcharger les opérateurs que vous souhaitez utiliser. Semblable à la réponse de James McNellis ci-dessus, mais vous permettant de le faire "automatiquement" chaque fois que vous opérez sur la variable en question.

class DualStateDouble 
{ 
public: 
    DualStateDouble(double &pv1,double &pv2) : m_pv1(pv1),m_pv2(pv2) 
    // overload all operators needed to maintain the relationship 
    // operations on this double automatically effect both values 
private: 
    double *m_pv1; 
    double *m_pv2; 
}; 
Questions connexes