Weisen Sie die abgeleitete Klassenadresse dem Basisklassenzeiger zu, dh der Basisklassenzeiger verweist auf das abgeleitete Klassenobjekt, was wir normalerweise als Polymorphismus bezeichnen.
Aber wenn es umgekehrt ist, muss die Kompilierung erzwungen werden, bevor es kompiliert werden kann
Laden Sie den Direktcode herunter:
#include usingnamespacestd; class Base { public: virtual void print() { cout<<"base"<print();//调用基类的print输出base pd->Derived::print();//调用派生类的print输出derived return 0; }
Ich würde gerne fragen, warum der Druck der Basisklasse aufgerufen wird, wenn pd->print() verwendet wird
Warum wird dann nach dem Entfernen des Virtuellen der Basisklasse der Ausdruck der abgeleiteten Klasse aufgerufen?
调用哪个虚函数是由对象所指的虚函数表所决定的,当你 new Base()的时候pb所指向的虚函数表中的虚函数是Base的,用(Derived*)强制转化并没改变,而非虚函数主要根据指针类型,也就是说pd一开始就是Derived,所以用Derived的函数,成员函数在调用时其实是调用了this指针的。
使用virtual的意思就是这个函数可以被子类override,使指向子类的父类指针不跟据指针本身的类别来调用这个函数,而(通过查虚函数表V-Table)调用被子类override后的函数。
值得一提的是
这样写是不正确,至少也是不安全的,不应该将指向父类对象的父类指针赋给子类指针。
此处的pd->print指向的是虚函数表中父类的的print,所以
调用的是Base::print
接下来
这是强行在父类对象上调用子类的函数(或者说以父类对象为this,强行调用虚函数表中的子类print),一般不推荐这么做。
还真是这样,刚运行了一下,确实很难理解。
我说一下我的思路,不知道对不对,大家可以参考一下:
第一种情况,写了virtual,如果成员函数加virtual,说明是动态绑定,只有在执行时候才会找到被调函数的地址。但是在哪里找呢?貌似每个对象的内存中都会存在一份虚表(也有说法是每个类有一份虚表,对象共享),因为你的Derived指针指向的是Base对象的那块内存,所以系统就去那块内存的虚表中找print函数,那块内存中虚表中的print函数的地址是Base类的print函数的地址,所以调用了基类的print函数
第二种情况:把virtual给去了,那就不涉及动态绑定,函数的地址是编译时候确定的。编译时候函数地址怎么确定呢:是通过在源程序符号表中查找所得。那么主程序中pd->print(),很明显,pd是Derived类,pd->print()相当于Derived::print,那编译器就到Derived类中找喽,所以编译时期把pd->print()中print()的地址替换成Derived::print的地址,所以就调用了子类的print函数。
不知道你明白我说啥不