C++总结之三 (虚函数和多态性)

4。虚函数——父类是虚,只需改变基类指针指向的派生类变量的地址,则调用的是实际派生类的函数,非基类函数

用基类的指针指向不同的派生类的对象时, 基类指针调用其虚成员函数,则会调用其真正指向对象的成员函数,而不是基类中定义的成员函数(只要派生类改写了该成员函数)。

以上这句话是否好理解?看下面这个例子:

假设B是A的派生类
A a;
B b;
A* p1=&a;
A* p2=&b;  关键就在这里,p2定义为指向A类的指针,但它实际指向的是b对象的地址,而 b是基于B类而来的对象。
p1->print();
p2->print();  看见了吗?这里调用的是A类的print.
}
如果在A中,把print 虚一下,加个virtual ,那么虽然P2定义指向A类的指针,由于实际指向了B类的对象,它调用的是B里面的print。
 这就是传说中的多态性!

virtual 只用来说明类声明中的原型,不能用在函数实现时。
具有继承性,基类中声明了虚函数派生类中无论是否说明,同原型函数都自动为虚函数。
虚函数是动态绑定的基础。本质:不是重载声明而是覆盖。
调用方式:通过基类指针或引用,执行时会 根据指针指向的对象的类,决定调用哪个函数。

int main(){   //为了在以后便于区分,我这段main()代码叫做main1
A a;
B b;
a.print();
b.print();  用对象,而不是指针,那么就直接调用B类的函数。

以上仅仅说明了什么是虚函数,那么它是如何做到的呢?

有虚函数的类的实例中这个表(虚函数的地址表)被分配在了 这个实例的内存中。也就是:把虚函数的地址表象数据一样存在实例的数据区。然后指向该父类的指针中,赋予该父类不同子类实例的地址,这样,该指针执行的虚函数将随着子类实例的不同而执行不同的函数。

在C++的标准规格说明书中说到,编译器必需要保证虚函数表的指针存在于对象实例中最前面的位置(这是为了保证正确取到虚函数的偏移量)。

posted on 2010-03-24 20:54  袁婉轩  阅读(381)  评论(0编辑  收藏  举报

导航