虚函数
没关系,下面就是实际的例子,相信聪明的你一看就明白了。
虽然在上面的图中我们可以看到Base1的虚表中有Derive的虚函数,但我们根本不可能使用下面的语句来调用子类的自有虚函数:Base1*b1=newDerive;b1->f1;//编译出错任何妄图使用父类指针想调用子类中的**未覆盖父类的成员函数**的行为都会被编译器视为非法,所以,这样的程序根本无法编译通过。
虚函数和纯虚函数都能做到这一点,区别是,子类如果不提供虚函数的实现,那就会自动调用基类的缺省方案。
基类的AnOperation()函数针对Product类进行操作,当然Product类一定也有多态(虚函数。
,”
??_7CD-szBase@@6B@就是上面提到的虚表,同时它也代表了虚表的地址。
“
**(2)抽象类的作用:**抽象类的主要作用是将有关的操作作为结果接口组织在一个继承层次结构中,由它来为派生类提供一个公共的根,派生类将具体实现在其基类中作为接口的操作。
虚函数声明如下:virtualReturnTypeFunctionName(Parameter);虚函数必须实现,如果不实现,编译器将报错,错误提示为:errorLNK****:unresolvedexternalsymbol”public:virtualvoid__thiscallClassName::virtualFunctionName(void)”3、对于虚函数来说,父类和子类都有各自的版本。
没了继承,什么都没得谈。
现在,我们跳进这个0x41bb38看一下,里面存了些什么!进入地址,发现了另一个指针变量。
实际上,优秀的程序员常常把基类的析构函数定义为虚函数。
这里我们着重看一下这张虚函数表。
在重复一遍虚函数实现的过程:通过对象内存中的vptr找到虚函数表vtbl,接着通过vtbl找到对应虚函数的实现区域并进行调用。
如果改为乘出租车,就简单多了,不必查行车路线,因为出租车什么地方都能去,只要在上车后临时告诉司机要到哪里即可。
由于A::fun()和A::fun2()是虚函数,所以&A::fun和&A::fun2获得的不是函数的地址,而是一段间接获得虚函数地址的一段代码的地址,我们形象地把这段代码看作那段CallVirtualFun。
把它定义为虚函数(实际上,在MFC中OnDraw不仅是虚函数,还是纯虚函数),可以保证时刻调用的是用户自己编写的OnDraw。
Add your comment