类虚函数

 

  理解C++中继承层次的关键在于理解如何确定函数调用,确定函数调用遵循以下四个步骤:

(1)首先确定进行函数调用的对象,引用或指针的静态类型。

(2)在该类中查找函数,如果找不到,就在直接基类中查找,如此循着类的继承链往上找,直到找到该函数或者查找完最后一个类。如果不能在类或其相关基类中找到该名字,则调用是错误的。

(3)一旦找到了该名字,就进行常规类型检查,查看如果给定找到的定义,该函数调用是否合法。

(4)假定函数调用合法,编译器就生成代码。如果函数是虚函数且通过引用或指针调用,则编译器生成代码以确定根据对象的动态类型运行哪个函数版本,否则,编译器生成代码直接调用函数。

 1 class Base{
 2 public:
 3     virtual int fcn();  
 4 }
 5 
 6 
 7 class D1: public Base{
 8 public: 
 9     //hides fcn in the base; this fcn is not virtual 
10     int fcn(int);   //nonvirtual function hides D1::fcn(int)
11     //D1 inherits definition of Base::fcn()
12 }
13 
14 class D2 : public D1{ 
15 public: 
16     int fcn(int);   //nonvirtual function hides D1::fcn(int)
17     int fcn();      //redefines virtual fcn from Base
18 }
19 
20 D1中的fcn版本没有重定义Base的虚函数fcn,相反,它屏蔽了基类的fcn。
21 结果D1有两个名为fcn的函数:1、类从Base继承了一个名为fcn的虚函数,
22 2、类又定义了自己的名为fcn的非虚成员函数,该函数接受了一个int的
23 形参。但是,从Base继承的虚函数不能通过D1对象(或D1的引用或指针)
24 调用,因为该函数被fcn(int)的定义屏蔽了。
25 
26 类D2重定义了它继承了两个函数,它重定义了Base中定义的fcn的原始版本
27 并重定义了D1中定义的非虚版本;
28 //通过基类调用被屏蔽的虚函数
29 //通过基类类型的引用或指针调用函数时,编译器将在基类中查找该函数而忽略派生类:
30     Base bobj;  D1 d1obj; D2 d2obj;
31     Base *bp1 = &bobj, *bp2 = &d1obj, *bp3 = &d2obj;
32     bp1->fcn();     //ok:virtual call, call Base::fcn at run time
33     bp2->fcn();     //ok:virtual call, call Base::fcn at run time
34     bp3->fcn();     //ok:virtual call, call D2::fcn at run time
35 
36 三个指针都是基类类型的指针,因此通过在Base中查找fcn来确定这三个调用,
37 所以这些调用是合法的;另外,因为fcn是虚函数,所以编译器会生成代码,
38 在运行时基于引用或指针所绑定的对象的实际类型进行调用。在bp2的情况,
39 基本对象是D1类的,D1类没有重定义不接受实参的虚函数版本,通过bp2的函数
40 调用(在运行时)调用Base中的定义的版本;

 

posted on 2015-04-29 17:33  阳台  阅读(241)  评论(0编辑  收藏  举报

导航