Je viens de comprendre virtuel et la substitution est utilisée pour (je ne peux pas trouver une utilisation si longtemps). Maintenant, je les utilise dans des modèles d'usine. Donc, ma question est ce que fait la virtuelle et le remplacement de la scène? Je suis prêt à aller à IL et à des trucs de code machine. P>
3 Réponses :
Je ne peux pas vous donner des idées sur la manière dont il est fait en IL mais la théorie de base est simple. P>
Lorsque le compilateur voit une déclaration de méthode forte> forte>, au lieu de la fixation de la méthode à la classe, elle l'ajoute à ce qu'on appelle un Maintenant, depuis le Ainsi, vous obtenez à la fois un héritage des méthodes des classes des parents et la capacité de modifier leurs définitions dans les classes d'enfants. P>
Pour plus d'informations, voir l'article Wikipedia sur le Table de la méthode virtuelle . P> gisible code> fort > (une table de méthode virtuelle) pour cette classe, qui contient des pointeurs vers des fonctions. P>
TTABLE CODE> STRORT> fait partie de la classe, il est hérité de ses sous-classes et donc les méthodes virtuelles sont également héritées. Vient maintenant le bit de remplacement. Lorsque le compilateur voit une déclaration forte> dans une déclaration de méthode, il lève les yeux sur
TTABLE code> strud>, trouve la méthode pour remplacer et modifier le pointeur de la fonction afin que Il pointe vers la nouvelle définition. P>
Pourrait-il s'agir de cette méthode dans une circuit à chaîner plutôt que de remplacer? Je vise simplement que, de la méthode de remplacement, nous pouvons appeler une méthode remplacée avec la base.
Je pense que la chaîne est implicite par héritage. Lorsque vous appelez la méthode de base, vous recherchez en réalité la définition de la méthode virtuelle définie par la classe de base et en appelant celui-ci. En effet, vous recherchez la table équipée de la classe de base et utilisez cela. C'est pourquoi vous devez l'appeler à l'aide de la base de toute façon, de sorte que le compilateur sait où regarder.
Non, en utilisant base.foo () code> n'entraîne aucune nouvelle recherche à table. Pourquoi la classe connaît-elle toujours sa classe de base, elle sait donc exactement quelle méthode invoquée dans un appel de base à la compilation.
Donc, si virtual est déclaré dans la classe de base, le remplacement de la classe héritée ne sera pas appelé, non? Parce que la compliance ne sait pas que la classe héritée existe du tout à la compilation. Et la ligne "lorsque le compilateur voit une substitution dans une déclaration de méthode" Cela se produit au moment de l'exécution alors comment cela pourrait-il arriver?
Oublier juste la deuxième question ci-dessus, j'ai eu la réponse de @HARPO
@Pavel: Oui, vous avez raison, je suis confus entre les opérations de compilée et d'exécution.
@Jonathan: Si la classe code> déclare une méthode
int doit () {retour 5; } code> comme virtuel puis lorsque
base b = nouvelle base (); INT A = B.DOIT (); code> est appelé, il appellera cette définition et
A code> sera
5 code>. Si une sous-classe
SUB: BASE CODE> remplace la même méthode que
INT DOIT () {Retour 6; } code> et vous exécutez:
base B1 = nouvelle base (); BASE B2 = Nouveau SUB (); Sub S = nouveau sous (); int A1 = b1.doit (); int A2 = b2.doit (); int A3 = s.doit (); code> vous obtiendrez
5 code>,
6 code> et
6 code> pour
A1 code >,
A2 code> et
A3 code> respectivement. Ainsi, chaque objet appelle seulement la définition fournie par sa classe actuelle.
@paracycle je sais complètement comment fonctionne la virtuelle. Je suis juste confondre que la classe est-elle remplacée au moment de l'exécution> la classe de base est un; hériter classe est B; un test = nouveau B; Sans le test virtuel.Jo () appellera la méthode Go () dans A, mais ma question initiale est si le «temps de compilation» ne sait pas sur B (car il est attribué à un type). Comment la version virtuelle (de cette méthode / fonction) peut appeler b. Mais de toute façon je suis assez clair maintenant.
Oh désolé, je pensais que c'était ce que j'essayais d'expliquer. Laissez-moi essayer rapidement de clarifier cela. Dans votre exemple, le compilateur sait que le type de l'objet "Test" est "B" même si vous l'utilisez comme "A". Ainsi, en mémoire, l'objet est représenté avec les membres / propriétés de "B", y compris la "Table" de "B". Lorsque vous l'utilisez comme "A", vous voyez juste une autre tranche de cette mémoire; Cependant, vous visuez toujours les mêmes adresses de mémoire, et plus important encore, la même "circonscription". Ainsi, un appel de méthode virtuelle se résout à celui de "B". Il n'y a pas de magie en cours. :)
Vous n'avez pas besoin d'aller dans l'IL - virtuel code> et
de remplacement code> engloutiez un concept d'orientation d'objet bien connu appelé polymorphisme . Effectivement, lorsqu'un procédé ou une propriété polymorphe est accessible, quelle méthode / propriété réellement em> s'applique est uniquement déterminée au moment de l'exécution. Sous le capot, fondamentalement, la méthode correcte (dans le cas d'une propriété, c'est une méthode également) est déterminée en accédant à une table de méthode virtuelle em> - une table de recherche pour trouver la bonne méthode, basée sur le type d'exécution. P>
Si vous êtes intéressé par l'IL, utilisez ildasm.exe pour consulter un programme compilé (DLL ou EXE). Vous verrez que les méthodes que vous marquez comme "virtuel" sont simplement marquées comme "virtuelles" dans l'IL. P>
La magie se produit dans le temps d'exécution. Le CLR construit une "table d'expédition de méthode" (ou "Table de méthode virtuelle"), qu'il utilise pour localiser les méthodes de votre classe en mémoire. Afin de permettre le polymorphisme, où le même nom de méthode signifie différentes choses en fonction du type d'exécution, une recherche supplémentaire est requise pour les méthodes virtuelles. (On pourrait dire qu'ils sont appelés des méthodes "virtuelles" précisément parce qu'elles sont sélectionnées "en vertu" de ce qu'ils fonctionnent - mais voir les commentaires de @ Pavel.) Joe Duffy le mettre de cette façon: P>
Un appel de méthode virtuelle est beaucoup comme un appel ordinaire, sauf que cela doit rechercher la cible de l'appel à Runtime basé sur le 'cet objet'. P> blockQuote>
Ce sont les bases. Don Box est une bonne lecture si vous voulez vraiment aller plus loin avec cela. P>
C'est une étymologie intéressante de virtuel code>, mais je serais curieux s'il s'agit d'une explication rétrospective (comme VB
Dim code> étant expliquée sous forme
déclarer en mémoire code> par Certains ces jours-là - à l'origine, c'était de
dimension code> et uniquement pour les tableaux), ou la vraie chose; Et si ce dernier, avez-vous des références? Je sais que
virtuel code> dans cette signification précise est apparu pour la première fois dans la toute première langue oo, Simula-67. Mais je ne me souviens pas de voir une explication du mot clé dans la référence de la langue pour cela ...
Ok, alors je sors sur un membre là-bas ... mais je me sens assez sûr. Declare-in-Memory est une nouvelle sur moi - je ne connaissais que comme le vieux mot-clé de dimensionnement de la matrice. Quoi qu'il en soit, content d'entendre d'un autre linguaphile.
Je crois que je l'ai trouvé. "Virtuel" est un raccourci pour "Quantité virtuelle"; Et la raison pour laquelle ils l'ont appelé de cette façon, c'était qu'ils ont envisagé à l'origine le mécanisme à utiliser principalement pour les attributs. Voir Books.Google.com/...
Wow, bonnes recherches. Franchement, je trouve le livre plutôt opaque pour le moment, mais je pense que je comprends votre explication. Cela semble un peu comme la façon dont Dim dépassés dans sa capacité déclarative de s'appliquer à des concepts plus larges (où "dimensionnement" ne s'appliquait pas). Pendant ce temps, la fonction virtuelle a pris plus que l'attribut virtuel. .NET n'a pas ajouté de propriétés virtuelles jusqu'à la version 2.0