48 votes

Remplacement de la fonction surchargée d'une base en C ++

Double Possible:
C++ résolution de surcharge

J'ai couru dans un problème où, après ma classe l'emportaient sur une fonction de sa classe de base, toutes les versions surchargées de fonctions sont alors cachées. Est-ce par sa conception, ou suis-je fait quelque chose de mal?

Ex.

class foo
{
  public:
    foo(void);
    ~foo(void);
    virtual void a(int);
    virtual void a(double);
};

class bar : public foo 
{
  public:
    bar(void);
    ~bar(void);
    void a(int);
};

le tableau suivant, puis donner une erreur de compilation disant qu'il n'y est pas une(double) de la fonction dans la barre.

main() 
{
  double i = 0.0;
  bar b;
  b.a(i);
}

73voto

Fred Larson Points 27404

Dans la catégorie bar, ajouter

using foo::a;

C'est une commune de la "chasse aux sorcières" en C++. Une fois un nom de correspondance est trouvée dans l'un contexte de classe, il n'a pas l'air, plus haut sur l'arbre d'héritage pour les surcharges. En spécifiant l'usage de la déclaration, vous apportez toutes les surcharges de 'a' à partir de 'toto' dans le champ d'application de la "barre". Ensuite, la surcharge fonctionne correctement.

Gardez à l'esprit que si il y a un code existant à l'aide de la " foo " de la classe, sa signification peut être modifié par des surcharges. Ou des surcharges pourrait introduire de l'ambiguïté et et le code ne parviennent pas à compiler. Cela est souligné dans James Hopkin de réponse.

21voto

Thomas L Holaday Points 7165

C'est la façon dont la langue utilisée au travail. Avant à l' aide de mots clés, si vous avez remplacé une fonction surchargée, vous avez eu de la surcharge de tous:

class bar : public foo 
{
  public:
    bar(void);
    ~bar(void);
    a(int);
    a(double d) { foo::a(d); }  // add this
}

Cette ennuyé assez de personnes que le comité des langues ajoutées à l' aide de la fonctionnalité, mais certaines vieilles habitudes ont la vie dure; et les habitués† avoir un bon argument.

Comme James Hopkins souligne, par l'ajout de l'aide, le programmeur est l'expression de l'intention de la classe dérivée, sans avertissement, ajouter les futurs remplacements de foo::a() à sa liste de signatures acceptables.

Voici un exemple de ce qu'il décrit:

#include <iostream>
class Base {
public:
  virtual void f(double){ std::cout << "Base::Double!" << std::endl; }
  // virtual void f(int) { std::cout << "Base::Int!" << std::endl; } // (1)
  virtual ~Base() {}
};

class Derived : public Base {
public:
  // using Base::f; // (2)
  void f(double) { std::cout << "Derived::Double!" << std::endl; }
};

int main(int, char **) {
  Derived d;
  d.f(21);
  return 0;
}

La sortie sera "Dérivée::Double!", parce que le compilateur va promouvoir l'argument entier pour un double. g++ 4.0.1 -Mur pas avertir que cette promotion s'est produite.

Décommentez (1) pour simuler un changement futur de la Base de l'ajout de la méthode de Base::f(int). Le code compile, encore une fois sans avertissement, même avec le Mur, et "Dérivés::Double!" reste à la sortie.

Maintenant décommenter (2) pour simuler une décision par le Dérivé programmeur pour inclure tous Base::f signatures. Le code se compile (sans mises en garde), mais la sortie est maintenant "Base: Int!".

† Je n'en pense pas un mot anglais pour "ceux qui ont l'habitude" et "accro" est beaucoup trop forte.

12voto

James Hopkin Points 8318

C'est par conception. La résolution de surcharge est limitée à une seule portée. Cela empêche certains cas désagréables de changement de code valide du sens lorsque des fonctions supplémentaires sont ajoutées à une classe de base ou à la portée d'un espace de noms.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X