基类的构造函数和析构函数不能被继承,基类成员的初始化只能在基类的构造函数中进行。

当创建一个派生类对象时,派生类的构造函数必须首先通过调用基类的构造函数来对基类的数据成员进行初始化,然后再执行派生类构造函数的函数体,对派生类新增的数据成员进行初始化。当派生类对象的生存期结束时,析构函数的调用顺序相反。

调用构造方式

  • 隐式调用:不指定基类的构造函数,默认调用基类默认构造函数(不带参数或者带默认参数值的构造函数)
  • 显式调用:指定调用基类的某个构造函数。除非基类有默认构造函数,否则都要用显示调用。

简而言之,如果基类有默认构造函数(包括两种情况:1. 不带形参表的构造函数;2. 带形参表,但是形参都有缺省值)的时候,派生类可以隐式调用这些构造函数,其他情况下,必须显式调用,指定基类的构造函数。

示例

隐式调用的情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <bits/stdc++.h>
using namespace std;

class A{
protected:
int m_a;
public:
//A (int a) : m_a(a) {}
A () {}
void show() {
cout << m_a << endl;
};
void seta(int a) {
m_a = a;
}
};

class B : public A {
private:
int m_b;
public:
B(int b) : m_b(b) {}
void display() {
cout << m_b << endl;
}
};

int main(void){
B b(1);
b.seta(5);
b.show();
b.display();
return 0;
}

/*
=====
5
1
=====
*/

显式调用的情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <bits/stdc++.h>
using namespace std;

class A{
protected:
int m_a;
public:
A (int a) : m_a(a) {}
void show() {
cout << m_a << endl;
};
void seta(int a) {
m_a = a;
}
};

class B : public A {
private:
int m_b;
public:
B(int b) : A(b), m_b(b) {}
void display() {
cout << m_b << endl;
}
};

int main(void){
B b(1);
b.show();
b.seta(5);
b.show();
b.display();
return 0;
}

/*
=====
1
5
1
=====
*/