Question

Je suis en train de résumer correctement une classe A, qui ne devrait être exploité par classe B.

Cependant, je veux hériter de la classe B.

Avoir un ami B ne fonctionne pas -. L'amitié est pas héritée

Quelle est la manière généralement acceptée de faire ce que je veux, ou que je fais une erreur?

Pour vous donner un peu plus de couleur, de classe A représente l'état d'un système complexe. Il ne doit être modifié par B, qui sont des actions qui peuvent être appliquées pour changer l'état de la classe A.

Était-ce utile?

La solution

Je suppose que vous voulez autoriser les descendants de B d'accéder directement A? Si A et B sont étroitement couplés, vous pouvez faire une définition de classe protégée au sein de B lui-même, au lieu d'être une définition indépendante. Par exemple.

class B
{
protected:
    class A
    {
    };
};

Une autre idée est de créer des méthodes protégées sur B qui délèguent leurs actions à A. par exemple.

class A
{
friend class B;
private:
    void DoSomething();
};

class B
{
protected:
    void DoSomething(A& a) { a.DoSomething(); }
};

Autres conseils

On dirait que vous devrez peut-être faire une refonte; votre classe A représente un État, mais votre classe B représente un ensemble d'actions. Il y a une relation là-bas, mais ce n'est pas une relation d'héritage. Je vous suggère de composition; vous voulez plus d'une relation de HASA qu'une relation ISA, pour autant que je peux dire.

Si je vous comprends bien, vous voulez avoir B et il est dérivés pour avoir accès à la mise en œuvre interne de la classe A, oui?

Malheureusement, C ++ n'a pas le concept de niveaux de protection "internes" que les langues comme C # et Java posses.

Vous pouvez envisager d'utiliser le privé (Pimpl) - également connu sous le nom des pointeurs opaques , pour exposer la fonctionnalité au sein de votre système en utilisant les niveaux d'accès public, que les consommateurs de A et B ne voient pas.

Garder tout comme il est, la meilleure chose à faire est d'ajouter des méthodes protégées à B qui donnent accès à la fonction équivalente de A, il aurait besoin. Cela ouvre l'encapsulation à seulement sous-classes de B.

La façon la plus simple de le faire est simplement d'avoir B contenir un A:

class B { protégé:   A a_; };

Ensuite, vous pouvez écrire une classe C qui hérite de B et est capable de manipuler A. Si C ne doit pas être en mesure de faire des choses arbitraires A, puis faire le soldat dans B et fournir des méthodes protégées en B que C peut utiliser pour faire des choses approuvées à A, comme ceci:

class B { privé:   A a_; protégé:   annuler doSomethingToA (); };

Le confinement est la voie à suivre (classe B contient parlementaire de type A), à moins B a besoin de remplacer des virtuals en A, auquel cas l'héritage privé est la chose la plus proche.

Je ne vois pas pourquoi vous voulez hériter. Faites tout dans un cadre privé et ami B. B a alors membre A qui peut librement manipuler.

La façon dont vous décrivez cela, il ressemble plus à la composition plutôt que l'héritage. Par exemple.

class ComplexMachine {
  public:
    setState(int state);
};

class Operator {
   public:
   Operator(ComplexMachine & m) :_m(m) {};

   void drive() { _m->setState(1); }
   void turn() { _m->setState(2); }
   void stop() { _m->setState(0); }

   private:
   ComplexMachine _m;   
};

class SmoothOperator : public Operator { }

Travailler avec les bits d'information que vous avez données:

Classe B devrait être responsable de la préservation des invariants de classe A et classe B devrait être la seule façon de manipuler A. Tout client - classe ou appelant dérivée -. Ne devrait pas besoin de savoir qu'il existe un

(De la conception POV, il n'y a même pas besoin A exister, mais je l'ai assez rencontré des raisons pratiques pour une telle séparation que je ne contre vous tenir;))

Cela peut nécessiter beaucoup de code boilerplate à écrire, ou ruser avec l'interface. par exemple. si le client doit être autorisé à utiliser une classe pour demander des informations, mais pas de le modifier, B pourrait remettre un const & le agrégée A. Avec un compilateur supportant __declspec (propriété) ou similaire, la douleur syntaxique peut être assouplie.

Si vous voulez être sûr que seul B fonctionne sur A, font l'instance d'un soldat et d'une interface protégée exposé de B à ses descendants.

class A
{
  public:
    void foo() {}
};

class B
{
  private:
    A a;

  protected:
    void CallAFoo() { a.foo() };
};

class C : public B
{
    void goo() { CallAFoo(); }
};

D'après ce que je comprends votre question, vous aurez besoin d'un polymorphisme . Vous avez besoin d'un mot-clé abstrait classe A et classe B hérite la classe A. En outre, le protégé permet aux classes qui héritent d'avoir accès à certaines informations tout en même temps refuser l'accès à quoi que ce soit d'autre. Voici un petit exemple:

// dynamic allocation and polymorphism
#include <iostream>
using namespace std;

class CPolygon {
  protected:
    int width, height;
  public:
    void set_values (int a, int b)
      { width=a; height=b; }
    virtual int area (void) =0;
    void printarea (void)
      { cout << this->area() << endl; }
  };

class CRectangle: public CPolygon {
  public:
    int area (void)
      { return (width * height); }
  };

class CTriangle: public CPolygon {
  public:
    int area (void)
      { return (width * height / 2); }
  };

int main () {
  CPolygon * ppoly1 = new CRectangle;
  CPolygon * ppoly2 = new CTriangle;
  ppoly1->set_values (4,5);
  ppoly2->set_values (4,5);
  ppoly1->printarea();
  ppoly2->printarea();
  delete ppoly1;
  delete ppoly2;
  return 0;
}

cplusplus.com (contient des informations sur les classes de polymorphisme et abstraits trop).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top