继承是面向对象编程中的一个核心概念,它允许一个类(子类/派生类)从另一个类(父类/基类)获得属性和方法。
1. 基类(Base Class)/父类(Parent Class)
被继承的类
提供通用的属性和方法
定义了子类的基本结构
2. 派生类(Derived Class)/子类(Child Class)
继承基类的类
可以使用基类的所有公有和保护成员
可以添加自己的新成员
可以重写(override)基类的方法
1. 代码重用
xxxxxxxxxx
101class Animal {
2public:
3 void eat() { cout << "Animal is eating" << endl; }
4 void sleep() { cout << "Animal is sleeping" << endl; }
5};
6
7class Dog : public Animal {
8public:
9 void bark() { cout << "Dog is barking" << endl; }
10};
2. 层次结构
形成类的层次关系
支持"is-a"关系(Dog is an Animal)
可以有多层继承
3. 多态性支持
通过虚函数实现运行时多态
基类指针可以指向派生类对象
1. 公有继承(public inheritance)
xxxxxxxxxx
41class Derived : public Base {
2 // 基类的public成员在派生类中仍为public
3 // 基类的protected成员在派生类中仍为protected
4};
2. 保护继承(protected inheritance)
xxxxxxxxxx
31class Derived : protected Base {
2 // 基类的public和protected成员在派生类中都变为protected
3};
3. 私有继承(private inheritance)
xxxxxxxxxx
31class Derived : private Base {
2 // 基类的public和protected成员在派生类中都变为private
3};
基类成员访问级别 | public继承 | protected继承 | private继承 |
---|---|---|---|
public | public | protected | private |
protected | protected | protected | private |
private | 不可访问 | 不可访问 | 不可访问 |
构造顺序
基类构造函数先执行
派生类构造函数后执行
析构顺序
派生类析构函数先执行
基类析构函数后执行
xxxxxxxxxx
111class Base {
2public:
3 Base() { cout << "Base constructor" << endl; }
4 ~Base() { cout << "Base destructor" << endl; }
5};
6
7class Derived : public Base {
8public:
9 Derived() { cout << "Derived constructor" << endl; }
10 ~Derived() { cout << "Derived destructor" << endl; }
11};
方法重写(Override)
派生类可以重新定义基类的方法:
xxxxxxxxxx
131class Animal {
2public:
3 virtual void makeSound() {
4 cout << "Animal makes a sound" << endl;
5 }
6};
7
8class Dog : public Animal {
9public:
10 void makeSound() override {
11 cout << "Dog barks" << endl;
12 }
13};
Note
创建、销毁的方式不能被继承 —— 构造、析构
复制控制的方式不能被继承 —— 拷贝构造、赋值运算符函数
空间分配的方式不能被继承 —— operator new 、 operator delete
友元不能被继承(友元破坏了封装性,为了降低影响,不允许继承)
1. 构造函数调用顺序
在单继承中,派生类对象的构造遵循"从基类到派生类"的顺序:
xxxxxxxxxx
231class Base {
2public:
3 Base() {
4 cout << "Base constructor called" << endl;
5 }
6 Base(int x) {
7 cout << "Base constructor with parameter: " << x << endl;
8 }
9};
10
11class Derived : public Base {
12public:
13 Derived() {
14 cout << "Derived constructor called" << endl;
15 }
16 Derived(int x, int y) : Base(x) {
17 cout << "Derived constructor with parameter: " << y << endl;
18 }
19};
20
21// 创建对象
22Derived obj; // 输出:Base constructor called
23 // Derived constructor called
2. 详细构造步骤
内存分配:为整个派生类对象分配内存空间
基类部分构造:调用基类构造函数初始化基类部分
成员变量初始化:按声明顺序初始化派生类的成员变量
派生类构造函数体执行:执行派生类构造函数的函数体
xxxxxxxxxx
181class Base {
2protected:
3 int base_value;
4public:
5 Base(int val) : base_value(val) {
6 cout << "Base constructor: base_value = " << base_value << endl;
7 }
8};
9
10class Derived : public Base {
11private:
12 int derived_value;
13public:
14 Derived(int base_val, int derived_val)
15 : Base(base_val), derived_value(derived_val) {
16 cout << "Derived constructor: derived_value = " << derived_value << endl;
17 }
18};
3. 构造函数初始化列表
派生类必须在初始化列表中调用基类构造函数(如果基类没有默认构造函数):
xxxxxxxxxx
121class Base {
2public:
3 Base(int x) { /* 基类只有带参构造函数 */ }
4};
5
6class Derived : public Base {
7public:
8 // 必须显式调用基类构造函数
9 Derived(int x, int y) : Base(x) {
10 // 派生类构造函数体
11 }
12};
1. 析构函数调用顺序
析构过程与构造过程相反,遵循"从派生类到基类"的顺序:
xxxxxxxxxx
191class Base {
2public:
3 ~Base() {
4 cout << "Base destructor called" << endl;
5 }
6};
7
8class Derived : public Base {
9public:
10 ~Derived() {
11 cout << "Derived destructor called" << endl;
12 }
13};
14
15// 对象销毁
16{
17 Derived obj;
18} // 离开作用域时输出:Derived destructor called
19 // Base destructor called
2. 详细析构步骤
派生类析构函数体执行:执行派生类析构函数的函数体
派生类成员变量析构:按声明顺序的逆序析构派生类成员
基类析构函数调用:自动调用基类析构函数
内存释放:释放整个对象的内存空间
xxxxxxxxxx
251class Base {
2protected:
3 int* base_ptr;
4public:
5 Base() : base_ptr(new int(10)) {
6 cout << "Base constructor: allocated memory" << endl;
7 }
8 ~Base() {
9 delete base_ptr;
10 cout << "Base destructor: freed memory" << endl;
11 }
12};
13
14class Derived : public Base {
15private:
16 int* derived_ptr;
17public:
18 Derived() : derived_ptr(new int(20)) {
19 cout << "Derived constructor: allocated memory" << endl;
20 }
21 ~Derived() {
22 delete derived_ptr;
23 cout << "Derived destructor: freed memory" << endl;
24 }
25};
1. 多态销毁问题
当通过基类指针删除派生类对象时,需要虚析构函数:
xxxxxxxxxx
171class Base {
2public:
3 virtual ~Base() { // 虚析构函数
4 cout << "Base destructor" << endl;
5 }
6};
7
8class Derived : public Base {
9public:
10 ~Derived() override {
11 cout << "Derived destructor" << endl;
12 }
13};
14
15// 正确的多态销毁
16Base* ptr = new Derived();
17delete ptr; // 正确调用:Derived destructor -> Base destructor
2. 非虚析构函数的问题
xxxxxxxxxx
171class Base {
2public:
3 ~Base() { // 非虚析构函数
4 cout << "Base destructor" << endl;
5 }
6};
7
8class Derived : public Base {
9public:
10 ~Derived() {
11 cout << "Derived destructor" << endl;
12 }
13};
14
15// 错误的销毁方式
16Base* ptr = new Derived();
17delete ptr; // 只调用Base destructor,未定义行为!
Tip
构造顺序:基类 → 派生类
析构顺序:派生类 → 基类
自动调用:基类析构函数会被自动调用
虚析构函数:多态场景下必须使用虚析构函数
异常安全:构造过程中如果发生异常,已构造的部分会被正确析构
初始化列表:派生类构造函数应在初始化列表中调用基类构造函数
当派生类定义了与基类同名的成员时,派生类的成员会隐藏基类的同名成员。这种隐藏是基于名称的,而不是基于签名的。
xxxxxxxxxx
181class Base {
2public:
3 void func() {
4 cout << "Base::func()" << endl;
5 }
6 void func(int x) {
7 cout << "Base::func(int): " << x << endl;
8 }
9 int value = 10;
10};
11
12class Derived : public Base {
13public:
14 void func() { // 隐藏了Base的所有func函数
15 cout << "Derived::func()" << endl;
16 }
17 int value = 20; // 隐藏了Base::value
18};
1. 名称隐藏规则
同名隐藏:派生类中的同名成员会隐藏基类中的所有同名成员
作用域优先:编译器首先在派生类作用域中查找,找到后不再向上查找
重载集合隐藏:即使函数签名不同,同名函数也会被整体隐藏
xxxxxxxxxx
211class Base {
2public:
3 void print() { cout << "Base::print()" << endl; }
4 void print(int x) { cout << "Base::print(int): " << x << endl; }
5 void print(double x) { cout << "Base::print(double): " << x << endl; }
6};
7
8class Derived : public Base {
9public:
10 void print(string s) { // 隐藏了Base的所有print函数
11 cout << "Derived::print(string): " << s << endl;
12 }
13};
14
15void test() {
16 Derived d;
17 d.print("hello"); // OK: 调用Derived::print(string)
18 // d.print(); // 错误:Base::print()被隐藏
19 // d.print(42); // 错误:Base::print(int)被隐藏
20 // d.print(3.14); // 错误:Base::print(double)被隐藏
21}
2. 数据成员隐藏
xxxxxxxxxx
171class Base {
2public:
3 int data = 100;
4 static int static_data;
5};
6
7class Derived : public Base {
8public:
9 int data = 200; // 隐藏Base::data
10 static int static_data; // 隐藏Base::static_data
11};
12
13void test() {
14 Derived d;
15 cout << d.data << endl; // 输出:200 (Derived::data)
16 cout << d.Base::data << endl; // 输出:100 (Base::data)
17}
1. 使用作用域解析运算符
xxxxxxxxxx
191class Base {
2public:
3 void show() { cout << "Base::show()" << endl; }
4 int value = 10;
5};
6
7class Derived : public Base {
8public:
9 void show() { cout << "Derived::show()" << endl; }
10 int value = 20;
11
12 void test() {
13 show(); // 调用Derived::show()
14 Base::show(); // 调用Base::show()
15
16 cout << value << endl; // 输出:20
17 cout << Base::value << endl; // 输出:10
18 }
19};
2. 使用using声明
xxxxxxxxxx
231class Base {
2public:
3 void func() { cout << "Base::func()" << endl; }
4 void func(int x) { cout << "Base::func(int)" << endl; }
5 void func(double x) { cout << "Base::func(double)" << endl; }
6};
7
8class Derived : public Base {
9public:
10 using Base::func; // 引入Base的所有func函数
11
12 void func(string s) { // 添加新的重载
13 cout << "Derived::func(string)" << endl;
14 }
15};
16
17void test() {
18 Derived d;
19 d.func(); // OK: Base::func()
20 d.func(42); // OK: Base::func(int)
21 d.func(3.14); // OK: Base::func(double)
22 d.func("hello"); // OK: Derived::func(string)
23}
1. 虚函数重写 vs 隐藏
xxxxxxxxxx
241class Base {
2public:
3 virtual void vfunc() { cout << "Base::vfunc()" << endl; }
4 virtual void vfunc(int x) { cout << "Base::vfunc(int)" << endl; }
5};
6
7class Derived : public Base {
8public:
9 void vfunc() override { // 重写Base::vfunc()
10 cout << "Derived::vfunc()" << endl;
11 }
12 // 注意:Base::vfunc(int)被隐藏了!
13};
14
15void test() {
16 Derived d;
17 Base* ptr = &d;
18
19 d.vfunc(); // Derived::vfunc() (重写)
20 ptr->vfunc(); // Derived::vfunc() (多态调用)
21
22 // d.vfunc(42); // 错误:Base::vfunc(int)被隐藏
23 ptr->vfunc(42); // OK: Base::vfunc(int)
24}
2. 解决虚函数隐藏
xxxxxxxxxx
201class Base {
2public:
3 virtual void vfunc() { cout << "Base::vfunc()" << endl; }
4 virtual void vfunc(int x) { cout << "Base::vfunc(int)" << endl; }
5};
6
7class Derived : public Base {
8public:
9 using Base::vfunc; // 引入所有vfunc
10
11 void vfunc() override { // 重写无参版本
12 cout << "Derived::vfunc()" << endl;
13 }
14};
15
16void test() {
17 Derived d;
18 d.vfunc(); // Derived::vfunc()
19 d.vfunc(42); // Base::vfunc(int) - 现在可以访问了
20}
完整示例
xxxxxxxxxx
1121
2
3using namespace std;
4
5class Base {
6public:
7 // 数据成员
8 int data = 100;
9 static int static_data;
10
11 // 普通函数重载
12 void print() {
13 cout << "Base::print()" << endl;
14 }
15 void print(int x) {
16 cout << "Base::print(int): " << x << endl;
17 }
18
19 // 虚函数重载
20 virtual void display() {
21 cout << "Base::display()" << endl;
22 }
23 virtual void display(string msg) {
24 cout << "Base::display(string): " << msg << endl;
25 }
26
27 virtual ~Base() = default;
28};
29
30int Base::static_data = 1000;
31
32class Derived : public Base {
33public:
34 // 隐藏基类数据成员
35 int data = 200;
36 static int static_data;
37
38 // 隐藏基类所有print函数
39 void print(double x) {
40 cout << "Derived::print(double): " << x << endl;
41 }
42
43 // 重写虚函数,但隐藏了其他重载
44 void display() override {
45 cout << "Derived::display()" << endl;
46 }
47
48 // 演示访问被隐藏成员的方法
49 void demonstrateAccess() {
50 cout << "\n=== 访问被隐藏的成员 ===" << endl;
51
52 // 访问数据成员
53 cout << "Derived::data = " << data << endl;
54 cout << "Base::data = " << Base::data << endl;
55
56 // 访问静态成员
57 cout << "Derived::static_data = " << static_data << endl;
58 cout << "Base::static_data = " << Base::static_data << endl;
59
60 // 访问函数
61 print(3.14); // Derived::print(double)
62 Base::print(); // Base::print()
63 Base::print(42); // Base::print(int)
64
65 // 访问虚函数
66 display(); // Derived::display()
67 Base::display("Hello"); // Base::display(string)
68 }
69};
70
71int Derived::static_data = 2000;
72
73// 使用using声明解决隐藏问题的类
74class DerivedWithUsing : public Base {
75public:
76 using Base::print; // 引入Base的所有print函数
77 using Base::display; // 引入Base的所有display函数
78
79 int data = 300;
80
81 // 添加新的重载
82 void print(double x) {
83 cout << "DerivedWithUsing::print(double): " << x << endl;
84 }
85
86 // 重写虚函数
87 void display() override {
88 cout << "DerivedWithUsing::display()" << endl;
89 }
90};
91
92int main() {
93 cout << "=== 成员隐藏演示 ===" << endl;
94
95 Derived d;
96 d.demonstrateAccess();
97
98 cout << "\n=== 多态调用 ===" << endl;
99 Base* ptr = &d;
100 ptr->display(); // Derived::display() (多态)
101 ptr->display("Polymorphic"); // Base::display(string)
102
103 cout << "\n=== 使用using声明解决隐藏 ===" << endl;
104 DerivedWithUsing d2;
105 d2.print(); // Base::print()
106 d2.print(42); // Base::print(int)
107 d2.print(3.14); // DerivedWithUsing::print(double)
108 d2.display(); // DerivedWithUsing::display()
109 d2.display("Test"); // Base::display(string)
110
111 return 0;
112}
输出结果:
xxxxxxxxxx
231=== 成员隐藏演示 ===
2
3=== 访问被隐藏的成员 ===
4Derived::data = 200
5Base::data = 100
6Derived::static_data = 2000
7Base::static_data = 1000
8Derived::print(double): 3.14
9Base::print()
10Base::print(int): 42
11Derived::display()
12Base::display(string): Hello
13
14=== 多态调用 ===
15Derived::display()
16Base::display(string): Polymorphic
17
18=== 使用using声明解决隐藏 ===
19Base::print()
20Base::print(int): 42
21DerivedWithUsing::print(double): 3.14
22DerivedWithUsing::display()
23Base::display(string): Test
多重继承中派生类对象的构造和析构比单继承更加复杂,涉及多个基类的初始化顺序、虚基类处理等问题。
多重继承定义
xxxxxxxxxx
171class A {
2public:
3 A() { cout << "A constructor" << endl; }
4 ~A() { cout << "A destructor" << endl; }
5};
6
7class B {
8public:
9 B() { cout << "B constructor" << endl; }
10 ~B() { cout << "B destructor" << endl; }
11};
12
13class C : public A, public B { // 多重继承
14public:
15 C() { cout << "C constructor" << endl; }
16 ~C() { cout << "C destructor" << endl; }
17};
基类构造顺序
多重继承中,基类的构造顺序由继承列表中的声明顺序决定,而不是初始化列表中的顺序。
xxxxxxxxxx
291class A {
2public:
3 A() { cout << "A constructor" << endl; }
4};
5
6class B {
7public:
8 B() { cout << "B constructor" << endl; }
9};
10
11class C {
12public:
13 C() { cout << "C constructor" << endl; }
14};
15
16// 构造顺序:A -> B -> C -> D
17class D : public A, public B, public C {
18public:
19 D() : C(), B(), A() { // 初始化列表顺序不影响构造顺序
20 cout << "D constructor" << endl;
21 }
22};
23
24void test() {
25 D obj; // 输出:A constructor
26 // B constructor
27 // C constructor
28 // D constructor
29}
内存分配:为整个派生类对象分配内存
基类构造:按继承列表顺序构造各个基类
成员变量初始化:按声明顺序初始化派生类成员
派生类构造函数体执行:执行派生类构造函数体
xxxxxxxxxx
271class Base1 {
2protected:
3 int value1;
4public:
5 Base1(int v) : value1(v) {
6 cout << "Base1 constructor: " << value1 << endl;
7 }
8};
9
10class Base2 {
11protected:
12 int value2;
13public:
14 Base2(int v) : value2(v) {
15 cout << "Base2 constructor: " << value2 << endl;
16 }
17};
18
19class Derived : public Base1, public Base2 {
20private:
21 int derived_value;
22public:
23 Derived(int v1, int v2, int v3)
24 : Base1(v1), Base2(v2), derived_value(v3) {
25 cout << "Derived constructor: " << derived_value << endl;
26 }
27};
析构顺序
析构顺序与构造顺序完全相反:
xxxxxxxxxx
91void test() {
2 {
3 D obj;
4 } // 离开作用域时输出:
5 // D destructor
6 // C destructor
7 // B destructor
8 // A destructor
9}
派生类析构函数体执行
派生类成员析构:按声明顺序的逆序
基类析构:按构造顺序的逆序
内存释放
xxxxxxxxxx
231class Base {
2public:
3 Base() { cout << "Base constructor" << endl; }
4 ~Base() { cout << "Base destructor" << endl; }
5};
6
7class A : virtual public Base {
8public:
9 A() { cout << "A constructor" << endl; }
10 ~A() { cout << "A destructor" << endl; }
11};
12
13class B : virtual public Base {
14public:
15 B() { cout << "B constructor" << endl; }
16 ~B() { cout << "B destructor" << endl; }
17};
18
19class C : public A, public B {
20public:
21 C() { cout << "C constructor" << endl; }
22 ~C() { cout << "C destructor" << endl; }
23};
虚基类的构造遵循特殊规则:
虚基类优先:所有虚基类首先构造
深度优先:按继承层次的深度优先顺序
左右顺序:同级别按继承列表顺序
最派生类负责:虚基类由最派生类直接构造
xxxxxxxxxx
131void test() {
2 C obj; // 构造顺序:
3 // Base constructor (虚基类)
4 // A constructor (第一个直接基类)
5 // B constructor (第二个直接基类)
6 // C constructor (派生类)
7
8 // 析构顺序:
9 // C destructor
10 // B destructor
11 // A destructor
12 // Base destructor
13}
虚基类初始化
xxxxxxxxxx
221class Base {
2public:
3 Base(int x) { cout << "Base(" << x << ")" << endl; }
4};
5
6class A : virtual public Base {
7public:
8 A(int x) : Base(x) { cout << "A constructor" << endl; }
9};
10
11class B : virtual public Base {
12public:
13 B(int x) : Base(x) { cout << "B constructor" << endl; }
14};
15
16class C : public A, public B {
17public:
18 // 必须直接初始化虚基类
19 C(int x, int y, int z) : Base(x), A(y), B(z) {
20 cout << "C constructor" << endl;
21 }
22};
复杂继承层次示例
xxxxxxxxxx
421
2using namespace std;
3
4class Base {
5public:
6 Base() { cout << "Base constructor" << endl; }
7 ~Base() { cout << "Base destructor" << endl; }
8};
9
10class A : virtual public Base {
11public:
12 A() { cout << "A constructor" << endl; }
13 ~A() { cout << "A destructor" << endl; }
14};
15
16class B : virtual public Base {
17public:
18 B() { cout << "B constructor" << endl; }
19 ~B() { cout << "B destructor" << endl; }
20};
21
22class C : public Base { // 非虚继承
23public:
24 C() { cout << "C constructor" << endl; }
25 ~C() { cout << "C destructor" << endl; }
26};
27
28class D : public A, public B, public C {
29public:
30 D() { cout << "D constructor" << endl; }
31 ~D() { cout << "D destructor" << endl; }
32};
33
34int main() {
35 cout << "=== 创建对象 ===" << endl;
36 {
37 D obj;
38 }
39 cout << "=== 对象销毁 ===" << endl;
40
41 return 0;
42}
输出结果:
xxxxxxxxxx
141=== 创建对象 ===
2Base constructor // 虚基类Base (通过A和B)
3A constructor // 第一个基类A
4B constructor // 第二个基类B
5Base constructor // 非虚基类Base (通过C)
6C constructor // 第三个基类C
7D constructor // 派生类D
8D destructor // 派生类D析构
9C destructor // 基类C析构
10Base destructor // 非虚基类Base析构
11B destructor // 基类B析构
12A destructor // 基类A析构
13Base destructor // 虚基类Base析构
14=== 对象销毁 ===
1. 显式调用基类构造函数
xxxxxxxxxx
171class Base1 {
2public:
3 Base1(int x) { cout << "Base1(" << x << ")" << endl; }
4};
5
6class Base2 {
7public:
8 Base2(int x) { cout << "Base2(" << x << ")" << endl; }
9};
10
11class Derived : public Base1, public Base2 {
12public:
13 Derived(int x, int y, int z)
14 : Base1(x), Base2(y) { // 显式调用基类构造函数
15 cout << "Derived(" << z << ")" << endl;
16 }
17};
2. 委托构造函数
xxxxxxxxxx
121class MultiBase : public Base1, public Base2 {
2public:
3 // 主构造函数
4 MultiBase(int x, int y) : Base1(x), Base2(y) {
5 cout << "MultiBase main constructor" << endl;
6 }
7
8 // 委托构造函数
9 MultiBase() : MultiBase(0, 0) {
10 cout << "MultiBase delegating constructor" << endl;
11 }
12};
Tip
构造顺序:按继承列表声明顺序,不是初始化列表顺序
析构顺序:构造顺序的完全逆序
虚基类优先:虚基类总是最先构造,最后析构
最派生类负责:虚基类由最派生类直接初始化
异常安全:构造失败时,已构造的基类会被正确析构
内存布局:多个基类子对象按顺序排列
虚析构函数:多态场景下必须使用虚析构函数
菱形继承是多重继承中最著名的问题,当一个类通过多个路径继承同一个基类时发生。
xxxxxxxxxx
261class Base {
2public:
3 int value = 10;
4 void show() { cout << "Base::show()" << endl; }
5};
6
7class A : public Base {
8public:
9 void funcA() { cout << "A::funcA()" << endl; }
10};
11
12class B : public Base {
13public:
14 void funcB() { cout << "B::funcB()" << endl; }
15};
16
17// 菱形继承:D继承了两个Base副本
18class D : public A, public B {
19public:
20 void funcD() {
21 // value = 20; // 错误:二义性
22 // show(); // 错误:二义性
23 A::value = 20; // 必须指定路径
24 B::show(); // 必须指定路径
25 }
26};
问题
内存浪费:同一个基类被复制多次
二义性:不知道访问哪个基类副本
数据不一致:多个副本可能有不同的值
xxxxxxxxxx
121void demonstrateProblem() {
2 D obj;
3 cout << "sizeof(Base): " << sizeof(Base) << endl; // 例如:8
4 cout << "sizeof(D): " << sizeof(D) << endl; // 例如:16 (两个Base)
5
6 // 访问不同的Base副本
7 obj.A::value = 100;
8 obj.B::value = 200;
9
10 cout << "A::value: " << obj.A::value << endl; // 100
11 cout << "B::value: " << obj.B::value << endl; // 200
12}
名称二义性
xxxxxxxxxx
221class Base1 {
2public:
3 void func() { cout << "Base1::func()" << endl; }
4 int data = 1;
5};
6
7class Base2 {
8public:
9 void func() { cout << "Base2::func()" << endl; }
10 int data = 2;
11};
12
13class Derived : public Base1, public Base2 {
14public:
15 void test() {
16 // func(); // 错误:二义性
17 // data = 10; // 错误:二义性
18
19 Base1::func(); // 正确:明确指定
20 Base2::data = 10; // 正确:明确指定
21 }
22};
类型转换二义性
xxxxxxxxxx
151void processBase1(Base1* ptr) {
2 cout << "Processing Base1" << endl;
3}
4
5void processBase2(Base2* ptr) {
6 cout << "Processing Base2" << endl;
7}
8
9void testAmbiguity() {
10 Derived obj;
11
12 // processBase1(&obj); // 错误:二义性转换
13 processBase1(static_cast<Base1*>(&obj)); // 正确
14 processBase2(static_cast<Base2*>(&obj)); // 正确
15}
xxxxxxxxxx
201// 如果两个基类都有相同名称但不同语义的函数
2class Conflicting1 {
3public:
4 virtual void process() { cout << "Process as type 1" << endl; }
5};
6
7class Conflicting2 {
8public:
9 virtual void process() { cout << "Process as type 2" << endl; }
10};
11
12class ConflictingDerived : public Conflicting1, public Conflicting2 {
13public:
14 // 必须明确重写哪个process
15 void process() override { // 错误:不明确重写哪个
16 // 解决方案:
17 Conflicting1::process();
18 Conflicting2::process();
19 }
20};
向上转换是指将派生类对象转换为基类类型,这种转换是安全的和隐式的。
xxxxxxxxxx
311class Base {
2public:
3 virtual void show() {
4 cout << "Base::show()" << endl;
5 }
6 virtual ~Base() = default;
7};
8
9class Derived : public Base {
10public:
11 void show() override {
12 cout << "Derived::show()" << endl;
13 }
14 void derivedOnly() {
15 cout << "Derived specific function" << endl;
16 }
17};
18
19void demonstrateUpcasting() {
20 Derived d;
21
22 // 隐式向上转换
23 Base* basePtr = &d; // 派生类指针 -> 基类指针
24 Base& baseRef = d; // 派生类引用 -> 基类引用
25 Base baseObj = d; // 对象切片(slicing)
26
27 // 多态调用
28 basePtr->show(); // 输出:Derived::show()
29 baseRef.show(); // 输出:Derived::show()
30 baseObj.show(); // 输出:Base::show() (切片)
31}
向上转换的特点
自动进行:编译器自动执行,无需显式转换
类型安全:总是安全的,不会失败
支持多态:通过虚函数实现动态绑定
可能发生切片:对象拷贝时丢失派生类特有部分
xxxxxxxxxx
181void analyzeUpcasting() {
2 Derived d;
3
4 cout << "=== 指针转换 ===" << endl;
5 Base* ptr = &d;
6 ptr->show(); // 多态调用
7 // ptr->derivedOnly(); // 错误:基类指针无法访问派生类成员
8
9 cout << "=== 引用转换 ===" << endl;
10 Base& ref = d;
11 ref.show(); // 多态调用
12
13 cout << "=== 对象切片 ===" << endl;
14 Base obj = d; // 发生切片
15 obj.show(); // 调用Base::show()
16 cout << "sizeof(Derived): " << sizeof(Derived) << endl;
17 cout << "sizeof(Base): " << sizeof(Base) << endl;
18}
向下转换是指将基类指针或引用转换为派生类类型,这种转换需要显式进行且可能不安全。
xxxxxxxxxx
231void demonstrateDowncasting() {
2 Derived d;
3 Base* basePtr = &d; // 向上转换
4
5 // 向下转换方法
6
7 // 1. static_cast(编译时转换,不安全)
8 Derived* derivedPtr1 = static_cast<Derived*>(basePtr);
9 derivedPtr1->show();
10 derivedPtr1->derivedOnly();
11
12 // 2. dynamic_cast(运行时转换,安全)
13 Derived* derivedPtr2 = dynamic_cast<Derived*>(basePtr);
14 if (derivedPtr2) {
15 derivedPtr2->show();
16 derivedPtr2->derivedOnly();
17 } else {
18 cout << "转换失败" << endl;
19 }
20
21 // 3. C风格转换(不推荐)
22 Derived* derivedPtr3 = (Derived*)basePtr;
23}
dynamic_cast
dynamic_cast
是最安全的向下转换方式,需要虚函数支持。
xxxxxxxxxx
471class Base {
2public:
3 virtual void show() { cout << "Base" << endl; }
4 virtual ~Base() = default;
5};
6
7class Derived1 : public Base {
8public:
9 void show() override { cout << "Derived1" << endl; }
10 void func1() { cout << "Derived1::func1" << endl; }
11};
12
13class Derived2 : public Base {
14public:
15 void show() override { cout << "Derived2" << endl; }
16 void func2() { cout << "Derived2::func2" << endl; }
17};
18
19void safeDynamicCast() {
20 // 创建不同类型的对象
21 Derived1 d1;
22 Derived2 d2;
23
24 Base* ptr1 = &d1;
25 Base* ptr2 = &d2;
26
27 // 安全的向下转换
28 Derived1* d1_ptr = dynamic_cast<Derived1*>(ptr1);
29 if (d1_ptr) {
30 cout << "成功转换为Derived1" << endl;
31 d1_ptr->func1();
32 }
33
34 // 失败的向下转换
35 Derived1* failed_ptr = dynamic_cast<Derived1*>(ptr2);
36 if (!failed_ptr) {
37 cout << "转换为Derived1失败" << endl;
38 }
39
40 // 引用的dynamic_cast
41 try {
42 Derived1& d1_ref = dynamic_cast<Derived1&>(*ptr1);
43 d1_ref.func1();
44 } catch (const bad_cast& e) {
45 cout << "引用转换失败: " << e.what() << endl;
46 }
47}
转换类型对比
转换类型 | 安全性 | 性能 | 使用场景 |
---|---|---|---|
向上转换 | 安全 | 高 | 多态、接口统一 |
static_cast | 不安全 | 高 | 确定类型的向下转换 |
dynamic_cast | 安全 | 低 | 不确定类型的向下转换 |
reinterpret_cast | 危险 | 高 | 底层类型转换 |
const_cast | 有限安全 | 高 | 移除const属性 |
当派生类没有显式定义复制构造函数时,编译器会自动生成一个默认的复制构造函数,它会:
调用基类的复制构造函数
对派生类自己的成员进行逐成员复制
xxxxxxxxxx
251class Base {
2public:
3 int baseData;
4
5 Base() : baseData(0) {}
6 Base(const Base& other) : baseData(other.baseData) {
7 std::cout << "Base复制构造函数" << std::endl;
8 }
9};
10
11class Derived : public Base {
12public:
13 int derivedData;
14
15 Derived() : derivedData(0) {}
16
17 // 显式定义派生类的复制构造函数
18 Derived(const Derived& other) :
19 // 首先调用基类的复制构造函数
20 Base(other),
21 // 然后复制派生类自己的成员
22 derivedData(other.derivedData) {
23 std::cout << "Derived复制构造函数" << std::endl;
24 }
25};
如果不在派生类复制构造函数的初始化列表中显式调用基类的复制构造函数,编译器会自动调用基类的默认构造函数(而不是复制构造函数)
派生类的复制构造函数只能访问基类的公有和受保护成员,不能访问私有成员
当派生类没有显式定义赋值运算符时,编译器会自动生成一个默认的赋值运算符,它会:
调用基类的赋值运算符
对派生类自己的成员进行逐成员赋值
xxxxxxxxxx
291class Base {
2public:
3 int baseData;
4
5 Base& operator=(const Base& other) {
6 if (this != &other) {
7 baseData = other.baseData;
8 }
9 std::cout << "Base赋值运算符" << std::endl;
10 return *this;
11 }
12};
13
14class Derived : public Base {
15public:
16 int derivedData;
17
18 // 显式定义派生类的赋值运算符
19 Derived& operator=(const Derived& other) {
20 if (this != &other) {
21 // 首先调用基类的赋值运算符
22 Base::operator=(other);
23 // 然后赋值派生类自己的成员
24 derivedData = other.derivedData;
25 }
26 std::cout << "Derived赋值运算符" << std::endl;
27 return *this;
28 }
29};
必须显式调用基类的赋值运算符,否则基类部分不会被赋值
应该检查自赋值情况(if (this != &other)
)
返回对象自身的引用,以支持连续赋值
Note
当派生类对象被赋值给基类对象时,会发生对象切片(object slicing):
xxxxxxxxxx
21Derived d;
2Base b = d; // 对象切片:只复制d的Base部分到b
这会导致:
只有基类部分被复制,派生类特有的成员被"切掉"
多态行为丢失,因为b是Base类型的对象,不再具有Derived的特性
当通过基类指针或引用复制多态对象时,默认的复制操作只会复制基类部分:
xxxxxxxxxx
21Base* ptr = new Derived();
2Base* copy = new Base(*ptr); // 只复制了ptr指向对象的Base部分
解决方案:虚拷贝构造模式
可以使用虚函数实现多态复制:
xxxxxxxxxx
181class Base {
2public:
3 virtual Base* clone() const {
4 return new Base(*this);
5 }
6 virtual ~Base() {}
7};
8
9class Derived : public Base {
10public:
11 virtual Derived* clone() const override {
12 return new Derived(*this);
13 }
14};
15
16// 使用
17Base* original = new Derived();
18Base* copy = original->clone(); // 调用Derived::clone(),创建完整的Derived对象
在多重继承中,派生类的复制构造函数需要调用所有基类的复制构造函数:
xxxxxxxxxx
231class Base1 { /* ... */ };
2class Base2 { /* ... */ };
3
4class MultiDerived : public Base1, public Base2 {
5public:
6 MultiDerived(const MultiDerived& other) :
7 Base1(other), // 调用Base1的复制构造函数
8 Base2(other), // 调用Base2的复制构造函数
9 memberData(other.memberData) {
10 }
11
12 MultiDerived& operator=(const MultiDerived& other) {
13 if (this != &other) {
14 Base1::operator=(other); // 调用Base1的赋值运算符
15 Base2::operator=(other); // 调用Base2的赋值运算符
16 memberData = other.memberData;
17 }
18 return *this;
19 }
20
21private:
22 int memberData;
23};