2010-05-08 13 views
2

je la hiérarchie suivante des classesComment remplacer facilement une classe de base

class classOne 
{ 
    virtual void abstractMethod() = 0; 
}; 

class classTwo : public classOne 
{ 
}; 

class classThree : public classTwo 
{ 
}; 

Tous classOne, classTwo et classThree sont des classes abstraites, et j'ai une autre classe qui définit les méthodes virtuelles pures

class classNonAbstract : public classThree 
{ 
    void abstractMethod(); 

    // Couple of new methods 
    void doIt(); 
    void doItToo(); 
}; 

et maintenant je dois différemment ... J'ai besoin comme

class classNonAbstractOne : public classOne 
{ 
    void abstractMethod(); 

    // Couple of new methods 
    void doIt(); 
    void doItToo(); 
}; 

class classNonAbstractTwo : public classTwo 
{ 
    void abstractMethod(); 

    // Couple of new methods 
    void doIt(); 
    void doItToo(); 
}; 

et

class classNonAbstractThree : public classThree 
{ 
    void abstractMethod(); 

    // Couple of new methods 
    void doIt(); 
    void doItToo(); 
}; 

Mais toutes les classes nonAbstract ont les mêmes nouvelles méthodes, avec le même code ... et je voudrais éviter de copier toutes les méthodes et son code à chaque classe nonAbstract. Comment pourrais-je accomplir cela?

Espérons qu'il est compréhensible ...

+0

Si elles contiennent le même code, de quoi avez-vous besoin pour les dérivations spécifiques ClassTwo et ClassOne? – KillianDS

+0

ClassOne a deux méthodes virtuelles qui sont surchargées dans ClassTwo et ClassThree ... ClassNonAbstract est juste ajouter la définition aux méthodes virtuelles pures – JTom

+0

introduire classe intermédiaire avec des fonctionnalités communes ou utiliser des modèles pour créer une classe générique (les modèles sont un sujet quelque peu difficile, vous devra lire à leur sujet si vous ne les utilisez jamais) – Anycorn

Répondre

4
template<class Base> 
struct Concrete : Base { 
    void abstractMethod(); 

    void doIt() { 
    // example of accessing inherited members: 
    int n = Base::data_member; // or this->data_member 
    n = Base::method(); // non-virtual dispatch 
    n = this->method(); // virtual dispatch 

    // since Base is a template parameter, 'data_member' and 'method' are 
    // dependent names and using them unqualified will not properly find 
    // them 
    } 
    void doItToo(); 
}; 

typedef Concrete<classOne> classNonAbstractOne; // if desired, for convenience 

Assurez-vous de donner à vos classes de base abstraites soit un destructor public virtuel ou faire le destructor protégé (il ne doit pas être virtuel, mais peut encore être).

Parce que le modèle doit être analysé avec des noms regardé sans savoir encore exactement ce que base sera, vous devez utiliser soit Base::member ou this->member d'accès membres hérités.

1

J'essaye généralement d'éviter l'héritage si possible (sauf pour les classes abstraites pures qui définissent des interfaces pures) parce qu'il crée un couplage étroit. Dans de nombreux cas, la composition est la meilleure alternative.

De plus, les choses ont tendance à être salissantes avec les structures d'héritage complexes. Ce n'est pas facile de dire à partir de votre description ce qui est le meilleur dans ce cas particulier. Juste en faisant remarquer cela comme une règle générale.

+0

Je vais +1 cela. Composition> héritage. Si doIt et doItToo ont le même code, placez-les dans la classe de base. ABC ne doit pas nécessairement être toutes des méthodes purement virtuelles - elles peuvent aussi être des méthodes normales et des variables membres. – Puppy

+0

Je ne peux pas le faire, parce que mes méthodes virtuelles pures sont pour les opérations de réseau et sont donc dépendantes de la plate-forme ... – JTom