2017-05-30 5 views
1

Lors de l'expérimentation du modèle de visiteur en C++, je suis arrivé à un problème idiot en ce qui concerne l'implémentation d'une interface dérivée. Je soupçonne que je ne sais pas comment formuler la question correctement, car je n'ai pas trouvé de solution à cela ailleurs.Interface dérivée de l'outil de struct C++

J'ai la struct base suivante:

struct Visitor { 
    virtual void visit(const Resources) = 0; 
    virtual void visit(const Population) = 0; 
}; 

Je déclare quelques réalisations concrètes de visiteur avec quelques fonctionnalités supplémentaires. Voilà comment je veux que mes déclarations à ressembler:

struct EndVisitor : public Visitor{ 
    virtual bool hasEnded(); 
}; 

struct SetupVisitor : public Visitor{ 
}; 

struct ScoreVisitor : public Visitor{ 
    virtual unsigned int getScore(); 
}; 

Lors de la définition, disons par exemple ScoreVisitor, l'IDE et le compilateur reconnaît les déclarations de fonctions supplémentaires dans ScoreVisitor:

unsigned int ScoreVisitor::getScore() { 
    return total; 
} 

Cependant, la mise en œuvre les fonctions des visiteurs ne sont pas reconnus par le compilateur ou IDE (Funtion 'visit' not declared in class 'ScoreVisitor'):

void ScoreVisitor::visit(const Resources resources) { 
    total += resources.score; 
} 

void ScoreVisitor::visit(const Population population) { 
    total += population.score; 
} 

Si je déclare ScoreVisitor répétant les fonctions de visiteur, le code compile, mais cela me laisse beaucoup de code copié-collé dans toutes les déclarations spécialisées de Visitor, que je souhaite éviter. Ce n'est pas ce que je veux que mes déclarations à ressembler:

struct ScoreVisitor : public Visitor{ 
    virtual void visit(const Resources); 
    virtual void visit(const Population); 
    virtual unsigned int getScore(); 
}; 

Comment puis-je déclare des versions spécialisées de visiteurs sans avoir à copier-coller toutes les fonctionnalités que le visiteur déclare déjà?

+3

Bienvenue dans C++! Vous devez déclarer tous les membres d'une classe correctement avant de les définir. Même les méthodes virtuelles que vous remplacez des classes de base. – Nim

+0

Merci Nim! Je comprends votre réponse comme: Je ne serai pas en mesure d'éviter de déclarer les fonctions d'interface dans une déclaration spécialisée de visiteur? – Yakitawa

+1

Oui, sauf si vous avez une hiérarchie où certaines fonctionnalités sont implémentées à différents niveaux d'abstraction. – Nim

Répondre

2

Il est impossible d'éviter de déclarer les méthodes que vous remplacez d'une classe de base dans une classe dérivée. C'est comme ça que la langue est. Généralement, les utilisateurs regroupent les fonctionnalités dans une forme de hiérarchie d'héritage pour exposer des fonctionnalités communes.

NOTE quelques questions liées à la syntaxe, virtual est facultative pour les classes dérivées (une fonction avec une signature similaire est virtuel par défaut), puisque C++ 11, certaines personnes ont commencé à employer override (je tombe dans cette catégorie aussi) car il attrapera - au moment de la compilation - tous les cas où, dans une classe dérivée, une méthode devrait être virtuelle, mais dans une classe de base, elle n'est pas déclarée comme telle.

Je suis sûr que ce qui précède est un exemple, mais il est essentiel de ne pas oublier un destructeur virtuel dans la classe de base!

1

Ce ne est pas idéal, mais vous pouvez le faire avec une sous-classe qui hérite de visiteurs et ont les autres classes dérivent de cette:

struct Visitor { 
    virtual void visit(const int) = 0; 
}; 

struct VisitorImplementor : public Visitor 
{ 
    virtual void visit(const int) override { /* implement */} 
}; 


struct EndVisitor : public VisitorImplementor { 
    virtual bool hasEnded() { return true; } 
}; 

Maintenant, vous pouvez créer des instances de EndVisitor et appeler visite sur elle

EndVisitor v; 

v.visit(10); 
+0

Merci Servé! Je vois comment l'implémentation des fonctions peut faire l'affaire en les rendant visibles dans les classes dérivées. Cependant, cela va dans la direction opposée de la question: je souhaite être aussi paresseux que possible, donc je voudrais garder à l'écart les implémentations des classes dérivées à l'exception des toutes dernières. – Yakitawa