9.3.1 派生类中构造函数的操作(1)
虽然前面说派生类不会继承基类的构造函数,但它们仍然存在于基类中,并且要用于创建派生类对象的基类部分。因为创建派生类对象的基类部分实际上属于基类构造函数而非派生类构造函数的任务。我们毕竟已经看到,基类的私有成员在派生类中虽然被继承下来,但却是不可访问的,因此这些任务必须交给基类的构造函数来完成。
在上一个示例中,默认的基类构造函数被自动调用,以创建派生类对象的基类部分,但情况不是必须这样。我们可以在派生类的构造函数中安排调用特定的基类构造函数,这样就能用非默认的构造函数初始化基类的数据成员,实际上就是可以根据给派生类构造函数提供的数据,选择调用特定的类构造函数。
试一试:调用构造函数
通过下面这个对上一个示例作了修改的版本,我们可以了解构造函数的实际工作情况。为了使派生类便于使用,我们确实需要给它提供一个允许指定对象尺寸的构造函数。为此,我们可以在派生类中再添加一个构造函数,从中显式调用基类的构造函数,从而设定那些从基类继承的数据成员的值。
在Ex9_03项目中,Box.h文件包含以下代码:
- // Box.h in Ex9_03
- #pragma once
- #include <iostream>
- using std::cout;
- using std::endl;
-
- class CBox
- {
- public:
- // Base class constructor
- CBox(double lv = 1.0, double wv = 1.0, double hv = 1.0):
- m_Length(lv), m_Width(wv), m_Height(hv)
- { cout << endl << "CBox constructor called"; }
-
- //Function to calculate the volume of a CBox object
- double Volume() const
- { return m_Length*m_Width*m_Height; }
-
- private:
- double m_Length;
- double m_Width;
- double m_Height;
- };
CandyBox.h头文件应该包含下面的代码:
- // CandyBox.h in Ex9_03
- #pragma once
- #include <iostream>
- #include "Box.h"
- using std::cout;
- using std::endl;
-
- class CCandyBox: public CBox
- {
- public:
- char* m_Contents;
-
- // Constructor to set dimensions and contents
- // with explicit call of CBox constructor
- CCandyBox(double lv, double wv, double hv,
char* str = "Candy") -
:CBox(lv, wv, hv) - {
- cout << endl <<"CCandyBox constructor2 called";
- m_Contents = new char[ strlen(str) + 1 ];
- strcpy_s(m_Contents, strlen(str) + 1, str);
- }
-
- // Constructor to set contents
- // calls default CBox constructor automatically
- CCandyBox(char* str = "Candy")
- {
- cout << endl << "CCandyBox constructor1 called";
- m_Contents = new char[ strlen(str) + 1 ];
- strcpy_s(m_Contents, strlen(str) + 1, str);
- }
-
- ~CCandyBox()
// Destructor - { delete[] m_Contents; }
- };
嵌入<iostream>头文件的#include指令和两个using声明在这里不是绝对必要的,因为Box.h文件包含相同的代码,但放在这里也没有什么坏处。相反,加上这几条语句意味着如果因不再需要而从Box.h文件中将相同的代码删除,那么CandyBox.h仍然能够编译。
Ex9_03.cpp文件的内容如下:
- // Ex9_03.cpp
- // Calling a base constructor from a derived class constructor
- #include <iostream> // For stream I/O
- #include <cstring> // For strlen() and strcpy()
- #include "CandyBox.h" // For CBox and CCandyBox
- using std::cout;
- using std::endl;
-
- int main()
- {
- CBox myBox(4.0, 3.0, 2.0);
- CCandyBox myCandyBox;
- CCandyBox myMintBox(1.0, 2.0, 3.0, "Wafer Thin Mints");
-
- cout << endl
- << "myBox occupies " << sizeof myBox
// Show how much memory - << " bytes" << endl // the objects require
- << "myCandyBox occupies " << sizeof myCandyBox
- << " bytes" << endl
- << "myMintBox occupies " << sizeof myMintBox
- << " bytes";
- cout << endl
- << "myMintBox volume is " // Get volume of a
- << myMintBox.Volume(); // CCandyBox object
- cout << endl;
- return 0;
- }