必备技能10.4:调用基类的构造函数
当基类中定义了构造函数的时候,派生类必须显式地调用该构造函数来对对象的基类部分进行初始化。派生类通过使用扩展的派生类构造函数的声明方法来调用基类的构造函数。这种扩展的形式如下:
派生类的构造函数(参数列表): 基类的构造函数(参数列表);
{
//派生类构造函数体
}
其中,基类的构造函数就是派生类继承的基类的名称。注意,在上面的形式中使用了一个冒号来把基类和派生类的构造函数分开。如果一个派生类继承了多个基类,那么这些基类的构造函数都是通过冒号来分隔的。
下面的程序演示了如何把参数传入到基类的构造函数中。其中为TwoDShape类定义了一个构造函数用来完成对width和height属性的初始化。
// 为TwoDShape类增加构造函数
#include <iostream>
#include <cstring>
using namespace std;
//二维对象类
class TwoDShape
{
double width;
double height;
public:
//构造函数
TwoDShape(double w,double h)
{
width = w;
height = h;
}
void showDim()
{
cout << "Width and height are "
<< width << " and " << height << "\n";
}
//访问函数
double getWidth() { return width; };
double getHeight() { return height; };
void setWidth(double w ) { width = w ; };
void setHeight(double h ) { height = h; };
};
//Triangle类是从TwoDShape类中继承而来的
class Triangle : public TwoDShape
{
char style[20];
public:
// 构造函数
Triangle( char *str, double w, double h):TwoDShape(w,h)
{
strcpy(style,str);
}
double area()
{
return getWidth() * getHeight() / 2;
}
void showStyle()
{
cout << "Triangle is " << style << "\n";
}
};
int main()
{
Triangle t1("isosceles",4.0,4.0);
Triangle t2("right", 8.0, 12.0);
cout << "Info for t1:\n";
t1.showStyle();
t1.showDim();
cout << "Area is " << t1.area() << "\n";
cout << "\n";
cout << "Info for t2:\n";
t2.showStyle();
t2.showDim();
cout << "Area is " << t2.area() << "\n";
return 0;
}
其中,Triangle()通过调用了TwoDShape的构造函数并把w和h的值传入其中来完成对width和height的初始化,而不用自己再对其进行初始化了。它只需要对自己特有的值进行初始化即可,那就是style。这就使得TwoDShape类可以自由地按照自己的方式来构建自己的子对象。进一步来讲,TwoDShape类可以自由增加不为派生类所感知的功能,避免了既存代码的修改。
基类中定义的任何形式的构造函数都是可以被派生类的构造函数调用的。真正被调用的是那个和传入参数相匹配的构造函数。例如,下面的代码中队TwoDShape和Triangle类机进行了扩展,增加了构造函数:
// 为TwoDShape类增加构造函数
#include <iostream>
#include <cstring>
using namespace std;
//二维对象类
class TwoDShape
{
double width;
double height;
public:
//缺省的构造函数
TwoDShape()
{
width = height = 0;
}
//构造函数
TwoDShape(double w,double h)
{
width = w;
height = h;
}
//构造高度和宽度相等的对象
TwoDShape(double x)
{
width = height = x;
}
void showDim()
{
cout << "Width and height are "
<< width << " and " << height << "\n";
}
//访问函数
double getWidth() { return width; };
double getHeight() { return height; };
void setWidth(double w ) { width = w ; };
void setHeight(double h ) { height = h; };
};
//Triangle类是从TwoDShape类中继承而来的
class Triangle : public TwoDShape
{
char style[20];
public:
//缺省的构造函数。这将自动调用TwoDShape的缺省构造函数
Triangle()
{
strcpy(style,"unknown");
}
//有三个参数的构造函数
Triangle( char *str, double w, double h):TwoDShape(w,h)
{
strcpy(style,str);
}
//构建一个等腰三角形
Triangle(double x):TwoDShape(x)
{
strcpy(style,"isoscoles");
}
double area()
{
return getWidth() * getHeight() / 2;
}
void showStyle()
{
cout << "Triangle is " << style << "\n";
}
};
int main()
{
Triangle t1;
Triangle t2("right", 8.0, 12.0);
Triangle t3(4.0);
t1 = t2;
cout << "Info for t1:\n";
t1.showStyle();
t1.showDim();
cout << "Area is " << t1.area() << "\n";
cout << "\n";
cout << "Info for t2:\n";
t2.showStyle();
t2.showDim();
cout << "Area is " << t2.area() << "\n";
cout << "\n";
cout << "Info for t2:\n";
t3.showStyle();
t3.showDim();
cout << "Area is " << t3.area() << "\n";
cout << "\n";
return 0;
}
上面程序的输出结果如下:
Info for t1:
Triangle is right
Width and height are 8 and 12
Area is 48
Info for t2:
Triangle is right
Width and height are 8 and 12
Area is 48
Info for t2:
Triangle is isoscoles
Width and height are 4 and 4
Area is 8
练习:
1. 派生类如何执行基类的构造函数?
2. 是否可以为基类的构造函数传入参数?
3. 哪个构造函数负责完成派生类对象中基类部分的初始化,是基类定义的构造函数还是派生类中定义的构造函数?