RSS

虚函数

编译器在编译时,会提供类似于CallVirtualFun这样的代码,当你调用虚函数时,其实就是先调用的那段类似CallVirtualFun的代码,通过这段代码,获得虚函数地址后,最后调用虚函数,这样就真正保证了多态性。

虚函数的作用,用专业术语来解释就是实现多态性(Polymorphism),多态性是将接口与实现进行分离;用形象的语言来解释就是实现以共同的方法,但因个体差异,而采用不同的策略。

析构pb时,首先调动派生类的析构,在调动基类的析构。

下面来看一段简单的代码classA通过classA和classB的print()这个接口,可以看出这两个class因个体的差异而采用了不同的策略,输出的结果也是我们预料中的,分别是ThisisA和ThisisB。

为了解决上述问题,引入了纯虚函数的概念,将函数定义为纯虚函数(方法:virtualReturnTypeFunction()=0;。

必须被子类继承重载以后,根据要求调用其子类的方法。

访问虚函数的时候通过vfptr间址找到vtable表,再间址进而找到要调用的函数。

这样就很好地解决了上述两个问题。

在一个成员初始化列表中同时出现对虚基类和非虚基类构造函数的调用时,虚基类的构造函数先于非虚基类的构造函数执行。

虚函数、纯虚函数类里如果声明了虚函数,这个函数是实现的,哪怕是空实现,它的作用就是为了能让这个函数在它的子类里面可以被覆盖(override),这样的话,编译器就可以使用后期绑定来达到多态了。

学习C++的多态性,你必然听过虚函数的概念,你必然知道有关她的种种语法,但你未必了解她为什么要那样做,未必了解她种种行为背后的所思所想。

这时候如果析构函数不是虚函数,就不能正确识别对象类型从而不能正确调用析构函数。

纯虚函数的意义,让所有的类对象(主要是派生类对象)都可以执行纯虚函数的动作,但类无法为纯虚函数提供一个合理的缺省实现。

假设我们有下面的类层次:classA如果你希望deletea的时候,会导致B::foo()被调用,那么你就错了。

它虚就虚在所谓推迟联编或者动态联编上,一个类函数的调用并不是在编译时刻被确定的,而是在运行时刻被确定的。

其他的编译器小弟不敢保证。

那么这个函数指针会跳转到那里去呢?我们按F10单步运行到这个call指令,然后按F11跟进去:00401032jmpParent::Function2(0040bfe0)00401037jmpParent::Parent(004010d0)→0040103CjmpChild::Function2(00401250)00401041jmpChild::Child(004011c0)光标停在了第三行,40103C的地方,执行这里的jmp指令后,又跳转到Child::Function2的位置,从而得到我们上面所看到的结果。

每当创建一个包含有虚函数的类或从包含有虚函数的类派生一个类时,编译器就会为这个类创建一个虚函数表(VTABLE)保存该类所有虚函数的地址,其实这个VTABLE的作用就是保存自己类中所有虚函数的地址,可以把VTABLE形象地看成一个函数指针数组,这个数组的每个元素存放的就是虚函数的地址。

现在用同一个指针变量(指向基类对象的指针变量),不但输出了学生stud1的全部数据,而且还输出了研究生grad1的全部数据,说明已调用了grad1的display函数。


Your Comment