2017-08-25 4 views
0

J'essaie de surcharger la fonction de la classe de base, mais comme je possède une classe enfant/dérivée/sous-classe je ne peux pas surcharger la fonction selon le type que j'instancie le modèle avec. J'ai donc pensé que peut-être je pourrais aussi templatiser la classe Base, de sorte que la fonction de classe de base renvoie aussi T. Mais si je fais cela, je ne serai pas capable de les garder dans un conteneur ou pointer vers eux, car ils seront tous de types différents. Je pensais aussi à la création de Base et à l'héritage d'un parent encore plus haut (qui n'est pas modélisé), mais je rencontre le même problème.Je ne peux pas remplacer la méthode de la classe Base parce que ma classe dérivée est modélisée

Y a-t-il un moyen de contourner ce problème?

+1

"* Je ne peux pas remplacer la méthode de la classe de base parce que ma classe dérivée est modélisée *" Ce n'est pas la raison pour laquelle vous ne pouvez pas remplacer. – juanchopanza

+0

Désolé, je me rends compte à quel point ça sonnait, vous avez raison. Pas seulement parce que je l'ai conçu, parce que j'ai des types de retour qui dépendent de l'argument template. – Zebrafish

+1

Pourquoi avez-vous * besoin * de remplacer une fonction virtuelle pure? On dirait que vous mélangez le polymorphisme statique et dynamique. – Bathsheba

Répondre

2

Vous pouvez faire si la valeur de retour T est covariant avec la valeur de retour de la fonction virtuelle pure. Mais malheureusement, un T ne sera pas, en général, covariant avec un double.

Accepter que vous mélanger les techniques polymorphisme statiques et dynamiques, ce qui pourrait être un défaut de conception, vous pouvez définir

struct Cov {}; 

avec

struct BaseType 
{ 
    virtual Cov& getPropertyValue() = 0; 
}; 

Ensuite,

template <typename T> 
struct NumberType : BaseType 
{ 
    T propertyValue; 
    T& getPropertyValue() override { return propertyValue; } 
}; 

T est un classe enfant de Cov: cette relation mea ns que T& est un type de retour qui est covariant avec Cov&, et ainsi la compilation réussira. En procédant ainsi, vous évitez également de copier une valeur de T. Vous pouvez également trouver pratique de construire conversion opérateurs pour les différents T qui finissent par être construits qui ont des valeurs de retour de type primitif.

Vous pouvez également introduire const types de retour de référence pour répondre précisément à vos besoins.

+0

À partir de l'exemple de code dans la réponse, ni 'int' ni' double' ne sont des classes enfant de 'Cov'. Cela ne résoudra pas le problème sans un équipement supplémentaire qui n'est pas expliqué dans la réponse. – skypjack

+0

C'est très très intéressant. Covariant, c'est le mot utilisé par Visual Studio, dit que ça doit être covariant. Cela semble très intéressant, je vais voir ce que je peux faire. – Zebrafish

+0

@skypjack Oui, c'est la première chose que je pensais, alors j'ai pensé que je vais juste envelopper les types de données primitifs dans les classes. Wow, il y a des solutions sans fin. OK, c'est probablement une mauvaise idée, mais j'aime quand même voir comme ça peut devenir fou. – Zebrafish

2

BaseType a un contrat qui lie tous ses descendants. Il dit dit que getPropertyValue renvoie double. NumberType ne pas modifier le contrat, il est enchâssé dans la pierre.

Faisons comme si le contrat n'était pas là.

BaseType& base = BaseContainer.getSome(); 

// base can be NumberType<complex> or 
// or NumberType<tensor<double,4,4,4>> or NumberType<padic<5>> 
// or a type that is not even thought of yet 
// as of now. 

what = base.getPropertyValue(); // how should 'what' be declared? 

Il n'y a pas moyen d'utiliser le résultat de base.getPropertyValue() si nous ne savons pas ce qu'elle est. Rendre le type de retour covariant n'aide pas vraiment. Il ne fait que déplacer le problème de BaseType à la classe de base BaseType::getPropertyValue() qui revient.

Vous devez créer une interface utilisable de BaseType et vous y tenir dans toutes les classes descendantes.

+0

Oui, c'est raisonnable. Avoir un upvote. – Bathsheba