Je pense que je comprends le concept de méthodes virtuelles et de vtales, mais je ne comprends pas pourquoi il y a une différence entre le passage de l'objet comme un pointeur (ou une référence) et le transmettre par la valeur (quel type de gaspillage quelque chose?)
Pourquoi quelque chose comme ce travail: p> et pas ceci ?: p> Material m = Texture();
poly->setMaterial(m);
// methods from Material are called if I pass the value around
7 Réponses :
Une fois que vous avez attribué un objet de texture à un matériau, il est tranché à un matériau. Par conséquent, tout appel sur l'objet M n'abandonnera que les fonctions matérielles.
Utiliser des structures simples, j'illeure ce qui est signifiait par trancher: p> matériau M code> a de l'espace pour exactement un objet de matériau. P>
Il n'y a aucun moyen de construire un objet code> texture code> pour vous, de sorte que l'objet est tranché em> à un objet de classe de base. p> matériau m = texture () code> appellerait le constructeur
matériau :: matériau (texture const &) code> ou, si cela n'est pas disponible, le matériel
< / Code> Copie Constructeur, qui construit un
matériau code> plutôt que par une texture code>. p>
Malgré le signe = code>, il n'y a pas d'affectation dans
type foo = bar; code>
@Frederverflow: Vous avez raison, corrigé cela. Je pensais qu'il y aurait si matériau code> n'a pas de constructeur de copie.
Petite correction: matériau m = texture () appellerait le constructeur matériau :: matériau (texture const &) code> ou defalut constructeur
matériau :: matériel () code> B> Puis opérateur d'affectation
matériau :: opérateur = (texture const &) code>
@Mihran hovsepian: Non. Il n'y a jamais d'affectation ici. Essayez-le.
@Mihran: En fait, ça ne le fait pas. Essayez de définir matériau code> avec CORTOR par défaut et
opérateur = code> mais copie privée cors.
Parce que si vous passez de valeur, alors Tranchement d'objet se produira et le polymorphisme d'exécution ne peut pas être atteint. Et dans votre code, la ligne même En outre, le polymorphisme d'exécution est réalisé à travers: p> Donc, si vous voulez un polymorphisme d'exécution, vous utilisez le pointeur em> ou référence em> du type de base, et voici quelques exemples comment vous pouvez atteindre le temps d'exécution POLYMORPHISME: P> matériau m = texture () code> provoque la tranchée d'objet. Donc, même si vous passez
m code> par pointeur (ou référence), le polymorphisme d'exécution ne peut pas être atteint.
Material* m1 = new Texture();
poly->setMaterial(m1); //achieved
Texture* t1= new Texture();
poly->setMaterial(t1); //achieved
Texture t2;
poly->setMaterial( &t2); //achieved : notice '&'
Material & m2 = t2;
poly->setMaterial( &m2 ); //achieved : notice '&'
Material m3;
poly->setMaterial( &m3 ); //NOT achieved : notice '&'
+1: la question si elle n'est pas 100% claire pour moi. Mais c'est aussi ma conclusion.
Merci, c'est probablement ce qui se passait dans mon code. La deuxième phrase de l'article Wiki était tout à fait la révélation: "Depuis que la superclasse n'a aucun endroit pour les stocker [les attributs de l'enfant]".
Je ne comprends pas votre déclaration. Que voulez-vous dire par écrit "Atteindre"? SetMaterial code> fonctionnera pour tous les
matériau code> Hiérarchie due au sous-type polymorphisme. Le polymorphisme est une propriété de
setmaterial code>, il vaut mieux dire "employé". Si nous disons que le polymorphisme ici est une capacité de travailler avec différents types qui ont une interface code> code>, puis chaque
getmaaterial code> invoke utilisera le polymorphisme (puisque
matériau code> La classe elle-même implémente son interface)
@RIGA: Par "Atteindre" Je voulais accéder à Texture code> à l'aide du pointeur de type
matériau * code>.
@Namaz, non, vous avez écrit "Atteindre le polymorphisme d'exécution", votre dernière déclaration "non réalisée" n'est pas correcte car le polymorphisme est obtenu en prenant un objet qui implémente une interface matériau code> à chaque fois. Comme vous l'avez indiqué précédemment, la fonction n'obtient pas un objet lui-même, mais un pointeur ou une référence. Cela fonctionne avec ce pointeur avec succès, le polymorphisme est utilisé.
@RIGA: Avez-vous lu ce que je voulais dire par "Atteindre le polymorphisme d'exécution"?
@Nawaz, Oh! Je vois! bool opérateur == (const obj & o1, const obj & o2) {retour o1! = O2; } code> c'est bon! Tu voulais juste quelque chose de différent! Approche solide.
parce que matériau m = texture (); code> tranches l'objet - à ce stade, vous avez simplement un matériau
p>. P>.
Material m = Texture(); This create a temporary Texture, then creates a Material by copying the Material part of Texture. This is called slicing, and is typically not what you want.
Il ne construit pas et copie ensuite; Il appelle le constructeur de copie.
Les fonctions virtuelles fonctionnent parfaitement dans vos deux exemples. Ils travaillent exactement comme ils sont censés travailler. P>
L'idée de la fonction virtuelle est qu'un appel à une telle fonction est expédié conformément au type dynamique em> de l'objet utilisé dans l'appel. (Malheureusement, vous n'avez pas montré dans vos exemples comment vous effectuez ces appels.) P>
Dans votre premier exemple, vous avez créé un objet de type Dans le second cas, vous créez un objet de type C'est tout ce qu'il y a. Tout fonctionne comme on peut s'attendre. Si vos attentes sont différentes de ceci, vous devriez simplement les apporter d'un meilleur alignement avec la langue. P> texture code>. Le type dynamique de l'objet est
texture code>, de sorte que les appels virtuels vont aux méthodes de
texture code>. p>
matériau code>. Le type dynamique de l'objet est code> matériau code>, de sorte que les appels virtuels vont aux méthodes de
matériau code>. P>
Je pense que le problème dans le deuxième exemple est qu'une texture sera tranchée dans un matériau sur la construction de la copie. Ainsi, toutes les fonctions virtuelles appelées sur m ne fonctionneront pas (comme un débutant attendu).
@Martin: Non. Le problème est que l'objet créé dans le deuxième exemple a le type matériau code>. Période. "Tranking" dans ce cas est complètement à côté du point. "Tranking" se produit pendant l'initialisation i> du nouvel objet. L'initialisation n'a pas d'importance. L'OP crée un objet de type
matériau code> - c'est la seule chose qui compte. Comment l'OP tente d'initialiser cet objet (avec «tranchant» ou sans) est totalement non pertinent.
Totalement en désaccord. Ils créent un objet de texture de type. Au moment où ils appellent des méthodes virtuelles, il n'est plus une texture, mais un objet important (c'est-à-dire le creux du problème). Ils obtiennent un matériel parce que la texture a été tranchée. Donc, le code fonctionne comme on pouvait s'y attendre. Le problème est que cela ne fonctionne pas car l'OP s'attend à ce que leur objet a été tranchée.
@Martin: non pertinent. Le deuxième code crée un objet nommé M code> de type
matériau code> et un objet temporaire de type
texture code>. Les appels virtuels sont effectués via l'objet
M code> de type
matériau code>. Le type de type
texture code> ne participe en aucun cas à des appels virtuels (cela ne peut tout simplement pas), c'est pourquoi il est totalement non pertinent. Les appels, encore une fois, sont effectués via
m code>, qui est
matériau code>. C'est la seule chose qui compte. Le fait que ce
m code> a été initialisé avec
texture () code> n'aime pas du tout. Le type i> de l'objet est ce qui compte. Comment cela a été initialisé est hors de propos.
@ Andreyt: Cela le rend hors de propos du système de course. Mais c'est ce fait exact qui en fait le la partie pertinente de la réponse. En fait c'est la réponse. C'est la seulement b> une partie de la réponse qui compte vraiment. Tout le reste n'est pas pertinent.
@Martin: Je ne suis pas d'accord. C'est en fait la raison pour laquelle l'OP a rencontré cette confusion en premier lieu: l'OP supposait que l'objet temporaire de la texture code> affectera en quelque sorte le comportement dynamique de l'objet final code> objet code>. En réalité, ce n'est pas le cas. La tranchée a effectivement lieu lors de l'initialisation de l'objet code> matériau code>. Cependant, depuis que la mise au point de cette question est le comportement virtuel, il est très important d'insister sur ce qui compte vraiment: le comportement virtuel dépend du type de l'objet et de rien d'autre. Tout le reste est à côté du point.
@Andrett: Oui c'est tout sur le comportement virtuel. Le comportement virtuel ne s'est pas produit à cause de la tranchée. Donc, l'erreur est le résultat de la tranchée qui a provoqué un changement de type inattendu. La tranchée a provoqué l'erreur afin que le tranchage soit le point. Si l'OP ne comprend pas que le tranchant s'est produit, ils répètent plus que probablement l'erreur.
class Base { //Members }; class Derived1:public Base { //Members }; int main() { Base obj1; Derived1 obj2; obj1 = obj2; //Allowed Since Public Inheritance } When obj1 = obj2 only those members of the Derived Class obj2 that are inherited from Base Class get copied in to obj1, rest of the members of Derived Class get sliced off. This is simply because Base class obj1 is not aware of members of Derived class. This phenomemon is called Object Slicing.In your case, when you call Material m = Texture() only contains members of Material and hence any function call on the object calls member functions of Material& not Texture.
Qu'est-ce que
poly code> et qu'est-ce que cela a à voir avec quelque chose? Où sont vos appels virtuels actuels? Comment se fait-il que votre méthode
SetMaterial code> peut accepter les deux pointeurs et les valeurs? Est-ce surchargé?
@Andreyt Ce n'était pas vrai code que je viens d'écrire deux exemples potentiels.
Génial, mais votre question concerne les appels virtuels. Pourtant, vos exemples (peu importe réels ni artificiels) n'incluent aucun appels virtuels pertinents du tout.