2010-10-20 7 views
0

J'ai 3 classes:Cast-order pour les classes héritées?

class Super 
{ 
    virtual int getType() { return 1; } 
} 
class Special : public class Super 
{ 
    virtual int getType() { return 2; } 
} 
class SpecialSpecial : public class Special 
{ 
    virtual int getType() { return 3; } 
} 

Et j'ai une fonction qui prend un std::vector<Super*> comme argument:

void handleClasses(std::vector<Super*> superVector) 
{ 
    foreach element in superVector //Pseudocode!! 
    { 
     if(element->getType() == 1) 
      std::cout << "Thats a SuperClass" << std::endl; 
     else if(element->getType() == 2) 
      std::cout << "Thats a SpecialClass" << std::endl; 
     else if(element->getType() == 3) 
      std::cout << "Thats a SpecialSpecialClass" << std::endl; 
    } 
} 

Il pourrait y avoir un utilisateur qui hérite de la classe Special:

class ParalellSpecial : public class Special 
{ 
    virtual int getType() { return 4; } 
} 

Maintenant, la fonction handleClasses ne peut pas comprendre la nouvelle classe avec le type 4, mais il devrait pouvoir o utiliser la classe supérieure suivante (dans ce cas, il s'agit de Special).

Comment quelqu'un pourrait-il implémenter une telle chose? Existe-t-il un modèle de conception qui permet de créer un ordre hiérarchique de classes et la super-classe suivante disponible sera utilisée comme solution de repli, si la classe actuelle n'a pas pu être utilisée (car elle est inconnue)?

REMARQUE: Les identificateurs de type sont uniquement à des fins de démonstration. Il existe sûrement de meilleures méthodes pour identifier un classtype en C++ (RTTI).

+1

Bon exercice, mais quel est le vrai problème? Pourquoi utilisez-vous if-else-if au lieu de simplement mettre du code réel dans cette méthode virtuelle? – sharptooth

+0

Tu ne peux pas déjà faire ça? Si le type est inconnu, vous retombez dans Special – Cratylus

+0

@userxxx: Il pourrait y avoir beaucoup de classes inconnues. Peut-être qu'un utilisateur hérite de 'super', puis hérite d'un autre userclass etc ... Il pourrait aussi y avoir plusieurs méthodes' handleClasses', qui comprennent en partie User-classes etc – MOnsDaR

Répondre

2

2 réponses possibles ici:

1) Si vous pensez que vous devez savoir quel type d'objet est vraiment, alors peut-être votre encapsulation est faux. Peut-être handleClasses() devrait appeler une méthode sur l'objet, et chaque classe devrait fournir une implémentation différente?

2) Si c'est l'une des rares fois où vous avez vraiment besoin de connaître le type d'un objet, utilisez dynamic_cast<>. C'est pour ça. E.g:

void handleClasses(std::vector<Super*> superVector) 
{ 
    foreach element in superVector //Pseudocode!! 
    { 
     if(dynamic_cast<SpecialSpecial *>(element) != 0) 
      // SpecialSpecial or a subclass of SpecialSpecial 
      std::cout << "Thats a SpecialSpecialClass" << std::endl; 
     else if(dynamic_cast<Special *>(element) != 0) 
      // Special or a subclass of Special 
      std::cout << "Thats a SpecialClass" << std::endl; 
     else 
      // Super or a subclass of Super 
      std::cout << "Thats a SuperClass" << std::endl; 
    } 
} 
+0

C'est une bonne idée, je pourrais commencer par essayer de faire 'dynamic_cast' dans' Super'. Si cela fonctionne, j'essaierai de 'dynamic_cast' dans une sous-classe de super etc. Cela continue jusqu'à ce que je trouve la classe la plus spécialisée dans mon arbre. Tout ce qui se passerait sous cela ne manquerait pas de jeter. – MOnsDaR

0

Cela dépend vraiment de votre problème réel. Habituellement, si vous avez des cas spéciaux pour chacune de vos classes que vous ne pouvez pas couvrir en utilisant le polymorphisme, alors l'héritage n'est probablement pas une bonne solution à votre problème.

Une autre idée serait de créer un registre de type global qui connaît les relations des types. Vous pouvez ensuite utiliser le registre pour vous déplacer dans la hiérarchie jusqu'à ce que vous trouviez un type que vous pouvez gérer. Le registre pourrait simplement être un DAG avec les identifiants de type en tant que nœuds.

+0

J'ai modifié la question originale. Le code ci-dessus devrait juste aider à comprendre le problème, il n'est pas un code réel compilable. Il suffit de l'appeler Pseudocode au lieu de C++ - Code valide si cela aide. – MOnsDaR

0

Une première solution pour obtenir la chose en mouvement:

Les enfants classes intègrent le type de superclasses dans leur propre type ID.
- Super reçoit le type == 1
- Special reçoit le type == 21
- SpecialSpecial reçoit le type == 321
- ParalellSpecial reçoit le type == 421

Le handleClasses vérifie maintenant si le premier chiffre est connu (ce qui n'est pas le cas pour ParalellSpecial) Ensuite, il vérifie si le second chiffre est connu (ce qui est le cas) puis imprime le message associé (ou fait ce qu'il veut faire, par exemple: Super à Special)

Ce concept présente le gros inconvénient qu'il ne peut y avoir que 10 classes par niveau hiérarchique. Aussi le concept de Type-Identifiers n'est pas optimal je pense.

Pensez qu'il existe de meilleures solutions disponibles.

Questions connexes