Double Possible:
C++ résolution de surchargeJ'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); }
Réponses
Trop de publicités?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.
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.