基类的构造函数和析构函数不能被继承,基类成员的初始化只能在基类的构造函数中进行。
派生类的数据成员包括基类的数据成员和派生类自身新增的数据成员。
1. 当创建一个派生类对象时,派生类的构造函数必须首先通过调用基类的构造函数来对基类的数据成员进行初始化,然后再执行派生类构造函数的函数体,对派生类新增的数据成员进行初始化。当派生类对象的生存期结束时,析构函数的调用顺序相反。
2. 派生类构造函数调用基类构造函数
隐式调用:不指定基类的构造函数,默认调用基类默认构造函数(不带参数或者带默认参数值的构造函数)
显式调用:指定调用基类的某个构造函数。除非基类有默认构造函数,否则都要用显示调用。
<派生类名>::<派生类名>(<形参声明>) : <基类名>(<参数表>)
{
<派生类构造函数的函数体>
}
基类有多个构造函数的话,编译器根据参数表来确定调用哪个
如果派生类没有定义构造函数,编译器会自动生成一个派生类默认构造函数,而且调用的是基类的默认构造函数。
所以说,如果基类没有定义构造函数,派生类可以不定义构造函数,或者不显示指定基类构造函数。否则,如果基类定义了带有形参表的构造函数(属于自定义构造函数而非默认构造函数),派生类就必须采取显式定义方式定义构造函数。
简而言之,如果基类有默认构造函数(包括两种情况:1.不带形参表的构造函数;2. 带形参表,但是形参都有缺省值)的时候,派生类可以隐式调用这些构造函数,其他情况下,必须显式调用,指定基类的构造函数。
#include <iostream>
using namespace std;
class Point{
protected:
int x,y; // protected成员,派生类以及派生类的派生类 的成员函数都可以访问
public:
Point(int a=0, int b=0)
{
x = a; y = b;
cout << "Point constructor: "<<x<<','<<y<<endl;
}
~Point()
{
cout << "Point destructor: "<<x<<','<<y<<endl;
}
};
class Circle : public Point{
protected:
int radius; // protected成员,派生类以及派生类的派生类 的成员函数都可以访问
public:
Circle(int a=0, int b=0, int r=0):Point(a,b)
{
radius = r;
cout << "Circle constructor: "<<x<<','<<y<<','<<radius<<endl;
}
~Circle()
{
cout << "Circle destructor: "<<x<<','<<y<<','<<radius<<endl;
}
};
class Cylinder:public Circle{
protected:
int height;
public:
Cylinder(int a=0,int b=0,int r=0, int h=0):Circle(a,b,r)
{
height = h;
cout << "Cylinder constructor: "<<x<<','<<y<<','<<radius<<','<<h<<endl;
}
~Cylinder()
{
cout << "Cylinder destructor: "<<x<<','<<y<<','<<radius<<','<<height<<endl;
}
};
int main()
{
Cylinder cylinder(400,300,200,100);
return 0;
}
输出:
Point constructor: 400,300
Circle constructor: 400,300,200
Cylinder constructor: 400,300,200,100
Cylinder destructor: 400,300,200,100
Circle destructor: 400,300,200
Point destructor: 400,300
如果Circle构造函数没有显式调用基类的构造函数Point(a,b),编译通过,运行结果就是Point的x和y都是0
多继承
多继承就是派生类有多个直接基类。
定义:
<派生类名>: <继承方式><基类名1>, <继承方式><基类名2>,...
构造函数
<派生类名>::<派生类名>(<形参声明>) : <基类名1>(<参数表1>), <基类名2>(<参数表2>)...
{
<派生类构造函数的函数体>
}
PS 派生类的形参要包含所有基类构造函数所需的参数多继承派生类的构造函数调用顺序:先调用所有基类的构造函数,然后再执行派生类的构造函数体。各基类的调用顺序取决于定义派生类时基类的指定顺序(class X : public A, public B, protected C, private D这种就是A->B->C->D->X,不管构造函数那里写的顺序是怎样的)。