9.3.1 派生类中构造函数的操作(2)
示例说明
除了在派生类中添加了一个构造函数以外,我们还在每个构造函数中添加了一条输出语句,以便了解各构造函数被调用的时间。对CBox类构造函数的显式调用出现在派生类构造函数函数头包含的冒号之后。可能我们已经注意到,这种语法无论怎么看都与在构造函数中初始化成员的语法完全相同:
- // Calling the base class constructor
- CCandyBox(double lv, double wv, double hv, char* str= "Candy"):
- CBox(lv, wv, hv)
- {
- ...
- }
这完全与我们在这里所做的事情一致,因为实质上我们就是在初始化派生类对象的CBox子对象。在第一个实例中,我们显然是在为初始化列表中的double类型成员m_Length、m_Width和m_Height调用默认的构造函数。在第二个实例中,我们是在调用CBox的构造函数。这样就使得在执行CCandyBox构造函数之前,先调用我们选定的CBox构造函数。
如果我们编译并运行该示例,则得到如下所示的输出:
- CBox constructor called
- CBox constructor called
- CCandyBox constructor1 called
- CBox constructor called
- CCandyBox constructor2 called
- myBox occupies 24 bytes
- myCandyBox occupies 32 bytes
- myMintBox occupies 32 bytes
- myMintBox volume is 6
表9-1解释了这几次构造函数的调用。
表 9-1
|
屏 幕 输 出< xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> |
被构造的对象 |
|
CBox constructor called |
MyBox |
|
CBox constructor called |
MyCandyBox |
|
CCandyBox constructor1 called |
MyCandyBox |
|
CBox constructor called |
MyMintBox |
|
CCandyBox constructor2 called |
MyMintBox |
第一行输出是CBox类的构造函数被调用的结果,起因源于CBox对象myBox的声明。第二行输出源于声明CCandyBox对象myCandyBox引起的对基类构造函数的自动调用。
注意:
基类构造函数总是先于派生类构造函数被调用。
第三行输出是为myCandyBox对象调用了默认的派生类构造函数造成的,该函数因为我们没有给对象myCandyBox提供初始化值而被调用。第四行输出源于CCandyBox对象的新构造函数中显式指明要调用CBox类的构造函数。为CCandyBox对象的尺寸指定的实参值被传递给基类的构造函数。最后一行输出来自新的派生类构造函数本身,因此这次仍然是先调用基类的构造函数,再调用派生类的构造函数。
当执行派生类的构造函数时,总是要调用基类的构造函数来构造派生类的基类部分。根据目前所看到的情况,我们对这一点应该没什么疑问了。如果我们不指定要使用的基类构造函数,编译器就安排调用默认的基类构造函数。
表9-1中的最后一行表明,myMintBox对象基类部分的初始化工作完全像我们预期的那样进行,那些private成员由CBox类的构造函数初始化。
基类的private成员只能被基类的函数成员访问总使人感到不方便。很多情况下,我们希望基类的private成员能够从派生类内访问。正如您此刻肯定已经预料到的那样,C++(www.cppentry.com)提供了这么做的方法。