C++ polymorphisme/l'héritage question: Redéfinition des fonctions de base vs fonctions virtuelles
Je sais que les classes dérivées peuvent simplement "redéfinir" membre de classe de base
fonctions, et que lorsque que la fonction d'un objet de classe dérivée est
appelée, la fonction définie dans la classe dérivée est utilisé, mais...
N'est-ce pas rendre le "virtuel" mot-clé redondant? J'ai lu de
certains évidemment des différences significatives entre ces deux cas (c'est à dire: si
vous avez une classe de base pointeur qui pointe vers une classe dérivée et que vous appelez
une fonction, si elle est virtuelle de la classe dérivée de la fonction sera
appelé, mais si pas, la classe de base de la fonction sera appelée).
Mettre une autre manière, quel est le but de être en mesure de redéfinir membre
fonctions en tant que non-fonctions virtuelles, et est-ce la plus couramment utilisée
la pratique?
Personnellement, il me semble qu'il serait juste de devenir très déroutant.
Merci!
OriginalL'auteur Russel | 2011-02-03
Vous devez vous connecter pour publier un commentaire.
L'approche la plus commune à la plus commune de la programmation orientée objet, les langages (Java, SmallTalk, Python, etc.) est d'avoir, par défaut, tous les membres de la fonction en tant que
virtual
.L'inconvénient, c'est qu'il y a une petite perte de performance pour chaque fois qu'un appel virtuel est faite. Pour cette raison, C++ vous permet de choisir si vous voulez que vos méthodes définies comme virtuelle, ou pas.
Cependant, il y a une différence très importante entre le virtuel et non virtuel méthode. Par exemple:
Le code exécuté lorsque l'
someVirtualMethod
appel est effectué dépend du type de béton de référence de pointeurp
, dépendant entièrement deSomeClass
sous-classes redéfinition.Mais le code exécuté sur le
someNonVirtualMethod
appel est clair: toujours l'un surSomeClass
, puisque le type de la variable p estSomeClass
.OriginalL'auteur vz0
On dirait que vous vous connaissez déjà la différence entre le virtuel et non virtuel méthodes, donc je ne rentrerai pas dans ce que les autres ont. La question est, quand une non-méthode virtuelle-être plus utile que le virtuel?
Il ya des cas où vous ne voulez pas la surcharge d'avoir une vtable pointeur inclus dans chaque objet, de sorte que vous prendre soin de s'assurer qu'il ya des pas méthodes virtuelles dans la classe. Prenons l'exemple d'une classe qui représente un point et est composé de deux membres,
x
ety
- vous pourriez avoir une très grande collection de ces points, et une vtable pointeur permettrait d'augmenter la taille de l'objet par au moins 50%.OriginalL'auteur Mark Ransom
Adressage: "autrement dit, quel est le but de être en mesure de redéfinir les fonctions de membre non-fonctions virtuelles, et est couramment utilisée pour la pratique?"
Bien, vous ne pouvez pas. Si la méthode de classe de base est virtuel, donc, est le correspondant de la méthode de la classe dérivée, si elle existe, si oui ou non le "virtuel" mot-clé est utilisé.
Alors: "N'est-il pas de rendre le "virtuel" mot-clé redondant? ".
Oui, il est redondants dans la méthode de la classe dérivée, mais pas dans la classe de base.
Cependant, notez qu'il est inhabituel (pour être poli) à souhaiter avoir une non-méthode virtuelle et ensuite redéfinir une classe dérivée.
OriginalL'auteur Keith
Il va travailler pour une instance de la classe dérivée et un pointeur vers la classe dérivée. Cependant, si vous passez votre classe dérivée dans une fonction qui prend un pointeur de Base, la version de Base de la fonction sera appelée. Ce n'est probablement pas souhaitable. Par exemple, le suivant sera de retour 5
C'est parce que de la façon virtuelle fonctionne. Lorsqu'un objet a un appel virtuel, le bon fonctionnement est vérifié dans la v-table lorsque vous appelez la fonction virtuelle. Sinon, vous n'avez pas vraiment héritage, vous avez le pointeur de la Base d'agir comme la classe de base pas de la classe dérivée.
OriginalL'auteur Steve
Il est important d'être prudent lors de l'destructeurs sont marqués comme non-virtuel et "remplacé" dans les classes dérivées - il est possible que la classe peut ne pas nettoyer correctement si le destructeur est appelé sur un pointeur vers la classe de base.
OriginalL'auteur Jimmy
semble que vous n'avez pas découvert la puissance de polymorphisme. Polymorphisme fonctionne de cette manière:
Vous avez une fonction qui prend un pointeur d'une classe de base, vous pouvez l'appeler en passant dans la classe dérivée des objets, en fonction des différents la mise en œuvre de la dérivée de la classe, la fonction va agir différemment. C'est une merveilleuse façon parce que la fonction est stable, même si nous étendons la hiérarchie de l'arborescence d'héritage.
sans ce mécanisme, vous ne pouvez pas atteindre cet objectif. Et ce mécanisme doit "virtuel"
OriginalL'auteur JQ.
C++ de cadrage et de nom-les règles de recherche permettent des choses très étranges, et les méthodes ne sont pas seuls ici. En effet Cacher (ou Ombrage) peut se produire dans de nombreuses situations différentes:
Alors, pourquoi ? Pour la résilience.
Lors de la modification d'un
Base
classe je ne sais pas du tout son possible des enfants. En raison de la règle de masquage (et en dépit de la confusion qu'elle peut créer), je peux ajouter un attribut ou d'une méthode et de l'utiliser sans un soin dans le monde:Base
méthode, si un enfant le remplacer ou pasIl est évident que si vous regardez le programme a fini de travailler, il n'a pas de sens, mais l'évolution des programmes et de la règle de masquage facilite l'évolution.
OriginalL'auteur Matthieu M.
La façon la plus simple d'expliquer c'est probablement ce:
En d'autres termes, si vous n'avez pas le mot-clé virtuel, et emportait une méthode, vous devez appeler la méthode manuelle [pardonnez-moi si ma mémoire en C++, la syntaxe est un peu rouillé dans les taches]:
Vous pourriez optimiser un peu (pour des raisons de lisibilité ET de la performance, le plus probable), à l'aide d'une table de recherche:
Maintenant, c'est plus d'un haut-niveau de l'approche. Le compilateur C++ peuvent évidemment optimiser un peu plus, en sachant exactement ce que "type_info", et ainsi de suite. Donc, probablement, à la place de la "carte" et la recherche "methodToCall = aDoSomethingVTable[typeid(chose)]", puis suivre ", le compilateur est l'insertion de quelque chose de beaucoup plus petit et plus rapide, comme "doSomethingWithAnA* A_doSomethingVTable;" suivi de "A_doSomethingTablething->type_number".
De sorte que vous êtes en droit que le C++ n'est pas vraiment BESOIN de virtuel, mais il ajoute beaucoup de sucre syntaxique pour rendre votre vie plus facile, et peut optimiser mieux aussi.
Cela dit, je pense que C++ est un terriblement obsolète de la langue, avec beaucoup de complications inutiles. Virtuel, par exemple, pourrait (et probablement devrait) être pris en charge par défaut, et optimisé où inutiles. Un Scala-comme "remplacer" le mot-clé serait beaucoup plus utile que le "virtuel".
OriginalL'auteur