Pourquoi une fonction virtuelle se cachés?
J'ai les classes suivantes:
class A {
public:
virtual void f() {}
};
class B : public A{
public:
void f(int x) {}
};
Si je dis
B *b = new B();
b->f();
le compilateur dit erreur C2660: "B::f' : la fonction ne prend pas de 0 arguments.
Ne pas la fonction dans B de la surcharge, puisque c'est une fonction virtuelle? Faire des fonctions virtuelles se cachent comme ça?
MODIFIER: j'ai en effet censé hériter de B à partir de A, qui montre le même comportement.
- Peut-être que vous souhaitez tirer
B
deA
?
Vous devez vous connecter pour publier un commentaire.
En supposant que vous avez prévu
B
de dériver deA
:f(int)
etf()
sont des signatures différentes, donc des fonctions différentes.Vous pouvez remplacer une fonction virtuelle avec une fonction qui a une signature compatible, ce qui signifie soit un nombre identique de la signature, ou celui dans lequel le type de retour est "plus spécifiques" (c'est la covariance).
Sinon, votre classe dérivée de la fonction masque la fonction virtuelle, tout comme tout autre cas où un dérivé de la classe déclare des fonctions avec le même nom que la base de fonctions de classe. Vous pouvez mettre
using A::f;
dans la classe B pour afficher le nomAlternativement, vous pouvez l'appeler comme
(static_cast<A*>(b))->f();
, ou commeb->A::f();
. La différence est que siB
ne fait remplacerf()
, le premier appelle le remplacer, alors que ce dernier appelle la fonction dansA
indépendamment.virtual
pas de cacher devrait se produire. Mais je le vois maintenant. Merci 🙂A * a = new B(); a.nonVirtualFunction()
appelleraA::nonVirtualFunction
, pasB::nonVirtualFunction
. Mais avec virtual fonctions, il va appelerB::nonVirtualFunction
, alors, évidemment,B::nonVirtualFunction
doit être à un minimum compatible avecA::nonVirtualFunction
.De classe B ne découlent pas d'Un donc pas de la fonction F() existe. Vous avez probablement dire:
Edit: j'ai raté la fonction de masquage. Voir Steve Jessop réponse pour une explication plus approfondie.
B
ne découle pas d'A
! +1Pas, et oui, respectivement. Si vous voulez que la surcharge de comportement, il faut dire
dans B.
B
n'est pas dérivé deA
B ne provient pas de l'Un, la déclaration correcte est:
Lorsque le compilateur a plus d'une façon de résoudre un symbole, c'est de choisir celui qui a la priorité, à moins que le code indique le contraire. Ce que vous attendez est la surcharge de prendre la priorité sur l'impérieuse. (plus de, plus de, plus de, aaaaack! Désolé, mais j'ai " plus de'whelmed).
Cet exemple a B hérite d'une méthode virtuelle dans laquelle la sous-classe fournit une version surchargée. Les surcharges sont des méthodes de la même classe avec le même nom de méthode mais des signatures différentes. Puisque B est une sous-classe de A, il est primordial de f(), ce qui signifie qu'il ne peut pas être une surcharge en même temps. C'est pourquoi il est caché.
Pour la classe A, déclarant méthode
virtuel signifie que la méthode va être résolu à l'aide d'un certain ensemble de règles qui ne sont pas compatibles avec votre déclaration de b.
Par la création de " b " comme une instance de "B", le compilateur n'a pas besoin d'utiliser la nature virtuelle de la méthode du même nom, "Un".
Si vous aviez déclaré 'b' de cette
l'appel b->f(); serait, en effet, se référer à la méthode dans Une en faisant usage de la résolution virtuelle.
Il semble qu'il existe assez semblable question avec réponse dans Biern de Stroustrup FAQ: http://www.stroustrup.com/bs_faq2.html#overloadderived
Comme il l'a dit:
mais si vous voulez