web-dev-qa-db-fra.com

redéfinir la méthode virtuelle c ++

J'ai un modèle de classe dans lequel certaines méthodes sont définies comme virtuelles pour donner à l'utilisateur de ma classe la possibilité de lui donner une implémentation dans sa classe dérivée. Notez que dans ma classe de modèles, certaines méthodes non virtuelles utilisent la méthode virtuelle (une classe virtuelle qui devrait renvoyer une valeur est appelée dans une classe non virtuelle).

Pouvez-vous me donner un exemple simple de code correct dans lequel la méthode virtuelle de la classe parente doit renvoyer une valeur (mais son implémentation est fournie dans une classe enfant) et la valeur renvoyée par la méthode virtuelle dans la classe parente est utilisée dans d'autres méthodes de cette classe. Parce que j'ai vu quelque part (par exemple ici: Remplacer en toute sécurité des fonctions virtuelles C++ ) que cela peut causer des problèmes et que la méthode définie par l'utilisateur notera la substitution de la méthode virtuelle de la classe parente.

Note: Je programme avec Code :: Blocks en utilisant le compilateur g ++.

EDIT: comme demandé ici un exemple simple de ce que je veux:

template<typename T>
class parent {
public:
  // Public methods that user can call
  int getSomething(T t);
  void putSomething(T t, int x);

  // public method that user should implement in his code
  virtual float compute(T t) { }

  // protected or private methods and attributes used internally by putSomething ...
  float doComplexeThings(...); // this can call
};

La méthode compute () doit être implémentée par l'utilisateur (la classe enfant). Cependant, cette méthode compute () est appelée par exemple par putSomething () et doComplexeThings ().

11
shn

Vous devez simplement vous assurer que les méthodes ont la même signature (y compris les modificateurs const/mutable et les types d'argument). Vous pouvez utiliser une définition virtuelle pure pour provoquer des erreurs de compilation si vous ne parvenez pas à remplacer la fonction dans une sous-classe.

class parent {
public:
  // pure virtual method must be provided in subclass
  virtual void handle_event(int something) = 0; 
};

class child : public parent {
public:
  virtual void handle_event(int something) {
    // new exciting code
  }
};

class incomplete_child : public parent {
public:
  virtual void handle_event(int something) const {
    // does not override the pure virtual method
  }
};

int main() {
  parent *p = new child();
  p->handle_event(1); // will call child::handle_event
  parent *p = new incomplete_child(); // will not compile because handle_event
                                      // was not correctly overridden
}
20
mschneider

Si vous pouvez utiliser les fonctionnalités de C++ 11 dans votre compilateur, les substitutions peuvent être étiquetées avec l'identifiant spécial override:

 float compute() override;

La ligne ci-dessus dans une classe dérivée provoquera une erreur de compilation car la fonction ne remplace pas une fonction membre de la base (signature incorrecte, argument manquant). Mais notez que cela doit être fait dans chaque classe dérivée, ce n'est pas une solution que vous pouvez imposer à partir de la classe de base.

À partir de la classe de base, vous pouvez seulement forcer le remplacement en rendant la fonction pure virtuelle, mais cela change la sémantique. Cela évite évite les problèmes en dépassant, mais plutôt force dans tous les cas. J'éviterais cette approche, et si vous voulez la suivre et qu'il existe une implémentation judicieuse pour le type de base, rendez la fonction virtuelle et fournissez une définition de sorte que l'implémentation de vos classes dérivées puisse simplement appeler les fonctions le type de base (c.-à-d. que vous forcez l'implémentation, mais dans les cas les plus simples, l'appel sera simplement transmis au parent)

Cette question est posée en 2013. C'est assez vieux mais j'ai trouvé quelque chose de nouveau qui n'existe pas dans les réponses.

Nous devons comprendre trois concepts: surcharge , écraser et cacher .

Réponse courte, vous voulez surcharger la fonction d'héritage de la classe de base. Cependant, la surcharge est le mécanisme permettant d'ajouter plusieurs comportements pour une fonction qui nécessite toutes ces fonctions sous la même échelle. Mais la fonction virtuelle est évidemment dans la classe Base.

class A {
public:
  virtual void print() {
    cout << id_ << std::endl;
  }
private:
  string id_ = "A";
};

class B : A {
public:
  using A::print;
  void print(string id) {
    std::cout << id << std::endl;
  }
};

int main(int argc, char const *argv[]) {
  /* code */
  A a;
  a.print();
  B b;
  b.print();
  b.print("B");
  return 0;
}

Ajouter en utilisant A :: print; dans votre classe dérive fera le travail!

Bien que je ne pense pas que ce soit une bonne idée, étant donné que la philosophie qui sous-tend la surcharge et l'héritage est différente, ce n'est peut-être pas une bonne idée de les imbriquer ensemble.

0
yuan