2017-06-17 3 views
-3

Considérons le schéma d'héritage et de composition suivant.fonctions virtuelles avec un type de retour non vide

// Exemple de programme

#include <iostream> 
#include <valarray> 

using namespace std; 

class TapProcessing 
{ 
    public: 
      TapProcessing(){}; 
      virtual ~TapProcessing(){}; 

      virtual void getWeights(valarray<double> &weights) {}; 
      virtual void getPrecisionWeights (valarray<double> &precWeights) {}; 
      virtual const uint &getTapIndex(const uint index) const 
      { 
       valarray<uint> a; 
       a.resize(10); 
       return a[index]; 
      }; //const {return 0;}; 
      virtual const uint &getTapIndexLow(const uint index) const 
      { 
       valarray<uint> a; 
       a.resize(10); 
       return a[index]; 
      }; //const {return 0;};; 
      virtual const uint &getTapIndexHigh(const uint index) const 
      { 
       valarray<uint> a; 
       a.resize(10); 
       return a[index]; 
      }; //const {return 0;}; 

}; 

class StepPrecisionTapProcessing : public TapProcessing 
{ 
    public: 
     StepPrecisionTapProcessing() { _tapIndex.resize(10, 3); } 
     ~StepPrecisionTapProcessing() {}; 

     void getWeights(valarray<double> &weights) { return weights.resize(10);} 
     virtual const uint &getTapIndex(const uint index) const {return _tapIndex[index]; } 

    private: 
      valarray<uint> _tapIndex; 

}; 

class HighPrecisionTapProcessing : public TapProcessing 
{ 
    public: 
     HighPrecisionTapProcessing() 
     { 
      _tapIndexLow.resize(10, 4); 
      _tapIndexHigh.resize(10, 5); 
     } 
     ~HighPrecisionTapProcessing() {}; 

     void getPrecisionWeights (valarray<double> &precWeights) { return precWeights.resize(10); }; 
     virtual const uint &getTapIndexLow(const uint index) const {return _tapIndexLow[index]; } 
     virtual const uint &getTapIndeHigh(const uint index) const {return _tapIndexHigh[index]; } 

    private: 
      valarray<uint> _tapIndexLow; 
      valarray<uint> _tapIndexHigh; 

}; 

class Generator 
{ 
    public: 
      Generator(bool isPrecision) 
      { 
       if (isPrecision) {_tp = new HighPrecisionTapProcessing(); 
       } 
       else { _tp = new StepPrecisionTapProcessing(); } 
      } 

      ~Generator() { delete _tp; } 

      const uint &getTapIndex(const uint index) const {return _tp->getTapIndex(index); } 
      const uint &getTapIndexLow(const uint index) const {return _tp->getTapIndexLow(index); } 
      const uint &getTapIndexHigh(const uint index) const {return _tp->getTapIndexHigh(index); } 

    private: 
      TapProcessing *_tp; 
}; 



int main() 
{ 
    Generator *G = new Generator(true); 
    uint index = 5; 

    cout<<"High tap index is = "<<G->getTapIndexHigh(index)<<endl; 

    delete G; 
    return 0; 
} 

Quand je lance principale, je reçois la sortie suivante,

haut indice du robinet est = 0

ici si la déclaration de getTapIndeHigh dans la classe dérivée remplace la déclaration dans la classe de base, nous verrons une valeur de 5 dans la sortie plutôt que 0. Pourquoi l'implémentation de la classe dérivée n'est pas prioritaire base celle de la méthode de classe pour les méthodes virtuelles non-nulles?

+2

"Est-il possible d'avoir une fonction virtuelle avec un type de retour non-nul?" Est-ce que tu l'as essayé? "Puis-je donner une valeur de retour fictive qui sera surchargée par le getter de classe dérivé?" Il semble qu'il vous manque une compréhension assez fondamentale de ce qu'est une fonction virtuelle. Il n'y a pas de «valeur de retour fictive». C'est soit la valeur de retour de la fonction appelée ou non. Voulez-vous une fonction virtuelle pure? C'est une fonction virtuelle sans définition dans la classe de base. https://en.wikipedia.org/wiki/Function_Virtual#Abstract_classes_and_pure_virtual_functions – xaxxon

+2

Le compilateur ne peut pas dire avec certitude que 'G' est une instance d'un objet' HighPrecisionTapProcessing'. Si, par exemple, 'G' était une instance de' StepPrecisionTapProcessing', qu'attendez-vous exactement de G-> getTapIndexHigh (index) 'pour revenir? Comme il n'y a pas de déclaration pour une fonction 'StepPrecisionTapProcessing :: getTapIndexHigh (uint)', runtime appelle la fonction de base 'TapProcessing :: getTapIndexHigh (uint)', pour laquelle vous n'avez pas fourni de définition avec une valeur de retour. Le compilateur a besoin de la fonction 'uint TapProcessing :: getTapIndexHigh (uint)' pour renvoyer une valeur 'uint'. –

+0

Vous voulez qu'un générateur contienne réellement un type particulier de TapProcessing, mais pour avoir une interface générale et une implémentation. Je ne sais pas pourquoi vous voudriez cela, mais si c'est vraiment ce que vous voulez, alors je ferais en sorte que votre classe de base TapProcesing lance des exceptions (avant un retour jamais exécuté si le compilateur se plaint encore) dans ses implémentations des fonctions, que vos classes dérivées remplaceront. De cette façon, si vous appelez la mauvaise fonction sur un générateur qui n'est pas supporté par le type sous-jacent, vous obtiendrez une exception à l'exécution en vous frappant pour ne pas connaître le type sous-jacent. – jschultz410

Répondre

0

Le problème vient de ces lignes ...

 virtual uint getTapIndex(uint index) {}; 
     virtual uint getTapIndexLow(uint index) {}; 
     virtual uint getTapIndexHigh(uint index) {}; 

Ils décrivent une fonction qui renvoie une uint, fournit une implémentation, mais ne retourne pas vraiment une valeur.

S'il existe une implémentation de base sensée, alors il est bon de la fournir. Cependant, ici, il semble que vous voulez une méthode pure virtual, rendant votre classe abstract. Vous voulez que toutes les classes dérivées implémentent une valeur. par exemple.

 virtual uint getTapIndex(uint index) =0; // require derived classes to implement 
     virtual uint getTapIndexLow(uint index) { return 0 } // can be overridden, but defaults to returning zero. 
     virtual uint getTapIndexHigh(uint index) = 0; // require derived classes to implement. 
+0

Donc le problème est que je ne veux pas implémenter getTapIndexHigh et getTapIndexLow dans StepPrecisionTapProcessing et de même getTapIndex dans HighPrecisionTapProcessing car ils n'appartiennent pas à cet emplacement. Les rendre purs virtuels me forceront à implémenter les trois méthodes dans les deux classes, ce qui va à l'encontre du but du polymorphisme dans ce scénario. – Naveen