相关内容:
- 基类的构造函数和析构函数不能被继承,基类成员的初始化只能在基类的构造函数中进行。
- 派生类的数据成员包括基类的数据成员和派生类自身新增的数据成员。
- 派生类对象生成时,会引发一系列构造函数调用,顺序是:先从上至下执行所有基类的构造函数,再按照成员对象的定义顺序执行各个成员对象的构造函数,最后执行自身的构造函数;而派生类对象消亡时,先执行自身的析构函数,然后按与构造的次序相反的顺序依次执行所有成员对象的析构函数,最后再从底向上依次执行各个基类的析构函数。
派生类构造函数调用基类构造函数:
- 隐式调用:不指定基类的构造函数,默认调用基类默认构造函数(不带参数或者带默认参数值的构造函数)
- 显式调用:指定调用基类的某个构造函数。除非基类有默认构造函数,否则都要用显示调用。
1
2
3
4
5
6
7<派生类名>::<派生类名>(<形参声明>) : <基类名>(<参数表>)
{
<派生类构造函数的函数体>
} - 基类有多个构造函数的话,编译器根据参数表来确定调用哪个;如果派生类没有定义构造函数,编译器会自动生成一个派生类默认构造函数,而且调用的是基类的默认构造函数。所以说,如果基类没有定义构造函数,派生类可以不定义构造函数,或者不显示指定基类构造函数。否则,如果基类定义了带有形参表的构造函数(属于自定义构造函数而非默认构造函数),派生类就必须采取显式定义方式定义构造函数。
- 简而言之,如果基类有默认构造函数(包括两种情况: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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
using namespace std;
class father
{
// 成员:略
public:
int X;
};
class son : public father
{
// 新的成员
public:
int Y;
};
class Base1
{
public:
Base1(int i)
{
b1 = i;
cout << "Base1的构造函数被调用。" << endl;
}
void Print() const
{
cout << b1 << endl;
}
private:
int b1;
};
class Base2
{
public:
Base2(int i)
{
b2 = i;
cout << "Base2的构造函数被调用。" << endl;
}
void Print() const
{
cout << b2 << endl;
}
private:
int b2;
};
class Base3
{
public:
Base3()
{
b3 = 0;
cout << "Base3定义的缺省参数的构造函数被调用。" << endl;
}
void Print() const
{
cout << b3 << endl;
}
private:
int b3;
};
class Member
{
public:
Member(int i)
{
m = i;
cout << "Member的构造函数被调用。" << endl;
}
int GetM()
{
return m;
}
private:
int m;
};
// 这个派生类继承了Base1,Base2,Base3三个基类;调用基类的顺序以此处进行继承时的声明顺序为准;
class Derived : public Base2, public Base1, public Base3
{
public:
Derived(int i, int j, int k, int l);
void Print();
private:
int d;
Member mem;// 定义成员对象,成员对象也要先于派生类进行构造;
};
// 调用基类的顺序和此处初始化列表中的基类顺序,无关; // 调用的时候,会默认的调用缺省的Base3();
// 注意:如果写为:Derived::Derived(int i, int j, int k, int l) :mem(k)则会默认的调用缺省参数的Base1(),Base2(),Base3(),如果自己没有写缺省的构造函数,C++会自动写一个;
Derived::Derived(int i, int j, int k, int l) : Base1(i), Base2(j), mem(k)
{
d = l;
cout << "Derived的构造函数被调用。" << endl;
}
void Derived::Print()
{
Base1::Print();
Base2::Print();
Base3::Print();
cout << mem.GetM() << endl;
cout << d << endl;
}
int main()
{
son a; // a是一个son,创建son对象,必须先创建father对象,这样才能进行继承;
a.X = 1;
a.Y = 2;
Derived obj(1, 2, 3, 4);
obj.Print();
return 0;
}代码执行结果:
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70#include <iostream>
using namespace std;
class Base
{
public:
Base() {
b1 = b2 = 0;
}
Base(int i, int j);
~Base();
void Print()
{
cout << b1 << ", " << b2 << ", " ;
}
private:
int b1, b2;
};
Base::Base(int i, int j)
{
b1 = i;
b2 = j;
cout << "基类Base的构造函数被调用:" << b1 << ", " << b2 << endl;
}
Base::~Base()
{
cout << "基类Base的析构函数被调用:" << b1 << ", " << b2 << endl;
}
class Derived : public Base
{
public:
Derived()
{
d = 0;
}
Derived(int i, int j, int k);
~Derived();
void Print();
private:
int d;
};
Derived::Derived(int i, int j, int k) : Base(i, j), d(k)
{
cout << "派生类Derived的构造函数被调用。" << d << endl;
}
Derived::~Derived()
{
cout << "派生类Derived的析构函数被调用。" << d << endl;
}
void Derived::Print()
{
Base::Print();
cout << d << endl;
}
int main()
{
Derived objD1(1, 2, 3), objD2(-4, -5, -6);
objD1.Print();
objD2.Print();
return 0;// main函数执行到return的时候,程序结束,全部的对象都要死掉;
}代码执行结果:
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
using namespace std;
enum BREED {A,B,C,D,E,F};
class Mammal
{
public:
Mammal();
~Mammal();
//存取器函数
int GetAge() const { return itsAge; }
void SetAge(int age) { itsAge = age; }
int GetWeight() const { return itsWeight; }
void SetWeight(int weight) { itsWeight = weight; }
void Speak() const { cout << "Mammal的声音!\n"; }
void Sleep() const { cout << "shhh.I'm sleeping.\n"; }
protected:
int itsAge;
int itsWeight;
};
class Dog : public Mammal
{
public:
Dog();
~Dog();
BREED GetBreed() const { return itsBreed; }
void SetBreed(BREED breed) { itsBreed = breed; }
void WagTail() const { cout << "Tail wagging...\n"; }
void BegForFood() const { cout << "Begging for food...\n"; }
private:
BREED itsBreed;
};
Mammal::Mammal() : itsAge(3), itsWeight(5)
{
cout << "Mammal的构造函数被调用..." << endl;
}
Mammal::~Mammal()
{
cout << "Mammal的析构函数被调用..." << endl;
}
Dog::Dog() : itsBreed(A)
{
cout << "Dog的构造函数被调用..." << endl;
}
Dog::~Dog()
{
cout << "Dog的析构函数被调用..." << endl;
}
int main()
{
Dog Fido; // 会先调用基类的构造函数,再调用派生类的构造函数;
Fido.Speak(); // 派生类继承了基类的 public 成员函数;
Fido.WagTail();
cout << "Fido is " << Fido.GetAge() << " years old" << endl;
return 0; // 会先调用派生类的析构函数,再调用基类的析构函数;
}代码执行结果: