Attribuez l'adresse de la classe dérivée au pointeur de classe de base, c'est-à-dire que le pointeur de classe de base fait référence à l'objet de classe dérivée, ce que nous appelons habituellement le polymorphisme
Mais lorsqu'il est inversé, il faut forcer sa compilation avant de pouvoir l'être
.Téléchargez le code direct :
#include<iostream>
usingnamespacestd;
class Base
{
public:
virtual void print()
{
cout<<"base"<<endl;
}
};
class Derived:public Base
{
public:
void print()
{
cout<<"derived"<<endl;
}
};
int main(void)
{
Base * pb=newB ase();//定义基类指针
Derived * pd=(Derived*)pb;//赋值给派生类指针
pd->print();//调用基类的print输出base
pd->Derived::print();//调用派生类的print输出derived
return 0;
}
Je voudrais demander pourquoi l'impression de la classe de base est appelée lors de l'utilisation de pd->print()
Alors pourquoi après avoir supprimé le virtuel de la classe de base, l'impression de la classe dérivée est appelée
La fonction virtuelle à appeler est déterminée par la table de fonctions virtuelles pointée par l'objet. Lorsque vous créez Base(), la fonction virtuelle dans la table de fonctions virtuelles pointée par pb est Base (Dérivée*) pour forcer The. la conversion n'a pas changé et la fonction non virtuelle est principalement basée sur le type de pointeur, ce qui signifie que pd est dérivé depuis le début, donc en utilisant la fonction dérivée, la fonction membre appelle en fait ce pointeur lorsqu'elle est appelée.
Utiliser virtual signifie que cette fonction peut être remplacée par la sous-classe, de sorte que le pointeur de la classe parent pointant vers la sous-classe n'appelle pas cette fonction en fonction de la catégorie du pointeur lui-même, et (en vérifiant la table des fonctions virtuelles V-Table) appelle la fonction après avoir été remplacée par la fonction de sous-classe.
Cela vaut la peine de le mentionner
Écrire comme ceci est incorrect, ou du moins, c'est dangereux. Le pointeur de classe parent pointant vers l'objet de classe parent ne doit pas être affecté au pointeur de sous-classe.
Le pd->print pointe ici vers l'impression de la classe parent dans la table des fonctions virtuelles, donc
L'appel est Base::print
Suivant
Il s'agit d'appeler de force la fonction de la sous-classe sur l'objet de classe parent (ou d'utiliser l'objet de classe parent comme ceci et d'appeler de force la sous-classe print dans la table de fonctions virtuelles).
C'est vraiment le cas. Je viens de le lancer et c'est vraiment difficile à comprendre.
Laissez-moi parler de ma réflexion. Je ne sais pas si c'est vrai ou non. Vous pouvez vous y référer :
Dans le premier cas, virtual est écrit. Si la fonction membre est ajoutée virtual, cela signifie qu'elle est liée dynamiquement. L'adresse de la fonction appelée ne sera trouvée que lors de l'exécution. Mais où le trouver ? Il semble qu'il y ait une table virtuelle dans la mémoire de chaque objet (on dit aussi que chaque classe possède une table virtuelle, qui est partagée par les objets). Parce que votre pointeur Derived pointe vers la mémoire de l'objet Base, le système va). à ce bloc. Recherchez la fonction d'impression dans la table virtuelle de la mémoire. L'adresse de la fonction d'impression dans la table virtuelle de la mémoire est l'adresse de la fonction d'impression de la classe de base. appelé
Deuxième cas : Si virtual est utilisé, la liaison dynamique n'est pas impliquée. L'adresse de la fonction est déterminée lors de la compilation. Comment déterminer l'adresse de la fonction lors de la compilation : elle s'obtient en recherchant dans la table des symboles du programme source. Ensuite, pd->print() dans le programme principal. Évidemment, pd est la classe Derived, et pd->print() est équivalent à Derived::print. Ensuite, le compilateur le recherchera dans la classe Derived, donc. pd est utilisé lors de la compilation. ->L'adresse de print() dans print() est remplacée par l'adresse de Derived::print, donc la fonction print de la sous-classe est appelée.
Je ne sais pas si tu comprends ce que je dis