【摘要】:对于派生类来说,基类的构造函数也应该像成员的类对象那样被显式调用,因为不同的派生类可能会调用不同版本的基类构造函数,只是之前的几个示例中我们都省略了,让系统自动调用了默认构造函数。此外,继承下的析构函数的调用顺序也是很有趣的。运行结果如图8.7.6所示:图8.7.6继承下的构造析构函数的调用顺序我们可以看到基类Base出现在了派生类的初始化列表中,并且我们用派生类构造函数的参数显式调用了基类构造函数。
对于派生类来说,基类的构造函数也应该像成员的类对象那样被显式调用,因为不同的派生类可能会调用不同版本的基类构造函数,只是之前的几个示例中我们都省略了,让系统自动调用了默认构造函数。此外,继承下的析构函数的调用顺序也是很有趣的。接下来让我们看一个示例:
动手写8.7.6
动手写8.7.6展示了继承下的构造析构函数的调用顺序。运行结果如图8.7.6所示:(www.xing528.com)
图8.7.6 继承下的构造析构函数的调用顺序
我们可以看到基类Base出现在了派生类的初始化列表中,并且我们用派生类构造函数的参数显式调用了基类构造函数。构造函数的调用顺序是很容易理解的,就算没有初始化列表,系统也会在派生类构造函数的函数体前调用基类的默认构造函数。那么为什么析构函数的顺序是反着的呢?我们先反过来看,如果基类声明了一个动态数组,而派生类在这个动态数组的每个元素上又声明了几个动态数组,那么在释放的时候我们当然要先释放每个元素上的动态数组,再释放基类的动态数组,而不是反过来进行,否则我们会直接删除了整个数组,元素上的动态数组的内存就无从释放了。换句话说,派生类的成员对基类可能有依赖关系,因此在释放资源的时候我们也要先释放派生类的成员,解决这层依赖关系,而不是釜底抽薪,从而导致意想不到的错误。
这也可以用栈的思想进行类比,构造函数相当于入栈,而在局部作用域中定义对象也确实是将内存分配到栈上。我们把基类构造完放到栈中之后,再把派生类构造完放到栈中,由于从栈中取元素的时候只能从最顶上开始,类似地,在释放内存的时候也需要先调用派生类的析构函数释放内存,再调用基类的析构函数。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。