C++ 学习基础十八——在构造(析构)函数中调用虚函数

C++语言规定:在某个类的构造函数(或析构函数)中调用虚函数,执行的是当前构造函数(或析构函数)所属类的虚函数的函数体。

以代码为例说明问题:

 1 class Point
 2 {
 3 public:
 4     Point(float x = 0,float y = 0)
 5     {
 6         printf("Point::Point() \n");
 7         size();
 8     }
 9     virtual void size(){printf("Point::size \n");}
10 };
11 
12 class Point3d : public Point
13 {
14 public:
15     Point3d(float x = 0,float y = 0,float z = 0)
16         :Point(x,y)
17         {
18             printf("Point3d::Point3d() \n");
19             size();
20         }
21     virtual void size(){printf("Point3d::size \n");}
22 };

当声明变量时:

 1 Point3d vd; 

打印结果为:

1 Point::Point() 
2 Point::size 
3 Point3d::Point3d() 
4 Point3d::size 

当子类Point3d的构造函数调用基类Point的构造函数时,在基类构造函数内访问虚函数void size()

实际上执行的是基类中对应的函数体Point::size(),而在子类Point3d中访问虚函数size()时,实际上执行的是子类中对应的函数体Point3d::size()。

 

这是因为虚表指针(vptr)的缘故。

vptr是虚函数指针,指向类的虚函数表。通过vptr找到虚函数表中对应的虚函数,这是C++多态的本质。

vptr初始化的时机:基类构造函数执行之后,程序员提供的代码或构造函数中初始化列表初始化之前。

所以才会出现开篇提到的情况。

 

总结构造函数的执行顺序:

1. 在派生类的构造函数中,所有的虚基类及基类的构造函数都会被执行。

2. 对象的虚表指针(一个或多个)被初始化,分别指向对应的虚函数表。

3. 如果有初始化列表,将在构造函数内扩展开来。这一步是在虚表指针初始化之后执行。

4. 执行程序员所提供的代码。

 

posted @ 2020-04-08 23:56  bky2016  阅读(989)  评论(0编辑  收藏  举报