C++ 继承

继承

继承的作用:解决代码的重用性;

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
class Human{
public:

Human(char* name, int age){
this->name = name;
this->age = age;
cout << "Human构造函数" << endl;
}

~Human(){
cout << "Human析构函数" << endl;
}

void say(){
cout << "说话:..." << endl;
}

private:
// 子类可以继承使用该权限修饰符下的变量和方法
//protected:
char* name;
int age;

};

class Man:public Human{
public:
// 继承后,子类构造方法,需要给父类初始化
// 注意,对象变量的初始化方式很相近
Man(char* name) :Human(name,12),h("Denny",10){
this->brother = name;

cout << "Man 构造函数" << endl;
}

~Man(){
cout << "Man析构函数" << endl;
}

void chasing(){
cout << "正在泡妞" << endl;
}

// 覆盖父类的方法
// 并非多态中的重写
void say(){
cout << "男人说:..." << endl;
}
private:
char* brother;

Human h;
};

// 创建时,先执行父类构造函数,销毁时,先执行子类析构函数
void func(){
Man man("jack");
}

void main(){
//Man m1("");
//m1.say();

// 子类实例可以赋值给父类对象,指针和引用
//Human h1 = m1;
//Human* h_p = &m1;
//Human& h = m1;

//func();

// 并非Java多态中的那种重写,而只是覆盖
Man m1("");
m1.say(); // 男人说:...
// 通过父类实例来接收,调用时指向的是父类的方法,而非子类的方法,
// 说明并非重写,只是覆盖了
Human h = m1;
h.say(); // 说话:...

// 在没有重写的情况下,子类仍然可以调用父类的方法
m1.Human::say();


system("pause");
}

继承权限组合

父类权限 子类继承方式 子类中 子类外
public public public public
public protected public protected
public private public private

protected public protected protected
protected protected protected protected
protected private protected private

private public private private
private protected private private

多继承

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
class Person{
public:
Person(char* name){

}
Person(char*name, int age){}
};

class Citizen{
public:
Citizen(int age){

}

public:

void say(){
cout << "saying..."<< endl;
}
};

class Student:public Person,private Citizen{
public:
// 多继承时,构造函数可以有不同的组合
Student(char*name) :Person(name),Citizen(10){

}
Student(char*name, int age) :Person(name,age), Citizen(age){
say();
}

};

虚继承解决同源继承二义性

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
class A{
public:
char* name;
};

class A1 :public A{

};

class A2 :public A{

};

class B :public A1, public A2{

};

void main(){
B b;
// 报错,存在二意性
b.name = "jack";

// 显式指定父类进行调用
b.A1::name = "rose";
b.A2::name = "jack";
}

通过虚继承,可以确保同源继承,只有一份相同的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class A1 :virtual public A{

};

class A2 :virtual public A{

};

void main(){
B b;
// 报错,存在二意性
// 当继承父类为virtual继承时,能够确保不同路径继承来的同名成员只有一份拷贝,解决二义性
b.name = "jack";
}