2013-07-09 3 views
2

J'ai déjà posté sur ce problème avant (Here), il s'agit d'une approche différente d'une solution. Cette solution semble mieux encapsuler le comportement de ceux qui implémentent la classe, puisqu'elle les empêche d'avoir explicitement besoin de lancer.C++ Utilisation de deux variables de même nom dans les classes dérivées et de base

Voici le problème:

J'ai un projet dans lequel je veux isoler le comportement de base dans la plupart des objets, tout en fournissant un comportement supplémentaire à travers des objets dérivés. Assez simple:

class BaseA 
{ 
    virtual void something() {} 
} 


class DerivedA : public BaseA 
{ 
    void something() {} 
    void somethingElse() {} 
} 

Maintenant, nous allons dire que j'ai aussi un deuxième ensemble de classes, même schéma d'héritage, sauf qu'ils agrègent les classes ci-dessus. Cependant, j'aimerais que la version de base utilise la classe de base et la version dérivée dans la classe dérivée. Ma solution je pensais à «cacher» la variable de classe de base en utilisant le même nom;

class BaseB 
{ 
    BaseA *var; 

    BaseB() 
    { 
     var = new BaseA(); 
    } 

    virtual void anotherThing1(); 
    virtual void anotherThing2(); 
    virtual void anotherThing3(); 
} 

class DerivedB : public BaseB 
{ 
    DerivedA *var; 

    DerivedB() 
    { 
     var = new DerivedA(); 
    } 

    void anotherThing1(); 
    void anotherThing2(); 
    void anotherThing3(); 
    void andAnother1(); 
    void andAnother2(); 
} 

L'objectif de cette approche est de sorte que les fonctions qui dépendent de la classe ne agrégée dérivée plus besoin de jeter explicitement pour obtenir la fonctionnalité acquise.

void func1(BaseB &b) 
{ 
    b.anotherThing1(); 
    b.var->something(); 
} 

void func2(DerivedB &b) 
{ 
    b.anotherThing1(); 
    b.andAnother1(); 
    b.var->something(); 
    b.var->somethingElse(); 
} 

void main(int argc, char **argv) 
{ 
    BaseB baseB; 
    DerivedB derivedB; 

    func1(baseB); 
    func1(derivedB); 
    func2(derivedB); 
} 

Cela serait-il considéré comme une mauvaise pratique?

+0

Pourquoi voulez-vous faire cela? Est-ce qu'un 'Base * var' ne ferait pas pour les deux? Si non, pourquoi voulez-vous qu'ils portent le même nom? Est-ce intentionnellement que cela empêche les autres de lire le code ou quelque chose? –

+0

J'essaie simplement d'obtenir des commentaires sur cette approche. J'ai d'abord pensé à utiliser une seule base * var (le lien au début de mon article). Mais je me demandais si cela serait plus facile pour ceux qui implémentent les classes puisqu'ils n'auraient jamais besoin de lancer explicitement des fonctionnalités dérivées – kbirk

Répondre

1

Cela serait-il considéré comme une mauvaise pratique?

Oui, ce serait une mauvaise pratique, car le var dans le Base serait utilisé. Il ne ressemble pas à DerivedB devrait être dérivez de BaseB: au contraire, ils doivent provenir de la même classe de base abstraite, comme ceci:

class AbstractB { 
public: 
    virtual void anotherThing1() = 0; 
    virtual void anotherThing2() = 0; 
    virtual void anotherThing3() = 0; 
}; 
class DerivedB1 : public AbstractB { // Former BaseB 
    BaseA *var; 

public: 
    DerivedB1() { 
     var = new BaseA(); 
    } 
    virtual void anotherThing1(); 
    virtual void anotherThing2(); 
    virtual void anotherThing3(); 
}; 
class DerivedB2 : public AbstractB { // Former DerivedB 
    DerivedA *var; 
public: 
    DerivedB2() { 
     var = new DerivedA(); 
    } 
    void anotherThing1(); 
    void anotherThing2(); 
    void anotherThing3(); 
    void andAnother1(); 
    void andAnother2(); 
}; 

Principe général utilisé ici est que vous devriez essayer de faire tout votre non classes de feuille dans votre résumé de hiérarchie d'héritage.

+0

Ouais j'espérais ne pas utiliser ce type de pattern, puisque presque chaque fonction surchargée dans une classe dérivée appelle simplement le version de base, puis exécute quelques lignes supplémentaires. Donc, en séparant complètement les classes, il y aura beaucoup de duplication de code. – kbirk

+0

@Pondwater Vous pouvez déplacer la fonctionnalité partagée dans une classe abstraite, avec des classes dérivées fournissant des ajustements spécifiques à la logique. Voir le motif [Template Method] (http://en.wikipedia.org/wiki/Template_method_pattern) (n'a rien à voir avec les templates C++). – dasblinkenlight

+0

La fonctionnalité partagée dépend de l'objet agrégé. Donc dans mon cas, anotherThing #() nécessite l'attribut var. DerivedB2 exigerait que var soit DerivedA. – kbirk

Questions connexes