6. 继承
6.1继承的基本语法
csharp
#include <iostream>
#include <string>
using namespace std;
// 公共的页面
// 继承的好处:减少重复代码
// 语法:class 子类 : 继承方式 父类
class BasePage{
public:
void header(){
cout << "首页 、公开课" << endl;
}
void footer(){
cout << "版权所有" << endl;
}
void left(){
cout << "左侧广告" << endl;
}
};
class Java : public BasePage{
public:
void content(){
cout << "java 文章内容" << endl;
}
};
class Python : public BasePage{
public:
void content(){
cout << "python 文章内容" << endl;
}
};
void test01(){
cout << "java 课程页面" << endl;
Java j;
j.header();
j.footer();
j.left();
j.content();
cout << "python 课程页面" << endl;
Python p;
p.header();
p.footer();
p.left();
p.content();
}
int main(int argc, char const *argv[]) {
test01();
return 0;
}
6.2 继承方式
继承的语法:class 子类 : 继承方式 父类
继承的三种方式
- 公共继承
- 保护继承
- 私有继承
csharp
#include <iostream>
#include <string>
using namespace std;
// 公共的页面
// 继承的好处:减少重复代码
// 语法:class 子类 : 继承方式 父类
class Base1{
public:
int m_A;
int m_B;
private:
int m_C;
};
class Son1 : public Base1{
public:
Son1(){
m_A = 100;
m_B = 200;
}
void func(){
cout << "son1 m_A = " << m_A << " m_B = " << m_B << endl;
}
};
class Son2 : protected Base1{
public:
Son2(){
m_A = 100; // 父类的公共权限,在子类中变为保护权限
m_B = 200;
}
void func(){
cout << "son2 m_A = " << m_A << " m_B = " << m_B << endl;
}
};
class Son3 : private Base1{
public:
Son3(){
m_A = 100; // 父类的公共权限,在子类中变为私有权限
m_B = 200;
}
void func(){
cout << "son3 m_A = " << m_A << " m_B = " << m_B << endl;
}
};
class GrandSon : public Son3{
public:
void func(){
// m_A = 100; // 到了Son3 类中,m_A 变为私有权限,不可以访问
}
};
void test01(){
Son1 s1;
s1.m_A = 100;
s1.func();
Son2 s2;
// s2.m_A = 100; // 保护权限下,不可以访问
s2.func();
Son3 s3;
// s3.m_A = 100; // 私有权限下,不可以访问
s3.func();
}
int main(int argc, char const *argv[]) {
test01();
return 0;
6.3 继承中的对象模型
csharp
#include <iostream>
#include <string>
using namespace std;
// 继承中的对象模型
class Base {
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
class Son : public Base {
public:
int m_D;
};
void test01() {
// 父类中所有非静态成员属性,都会被子类继承下来
// 父类中私有成员属性是被编译器给隐藏了,因此是访问不到的,但是确实是继承下来的
cout << "sizeof Son = " << sizeof(Son) << endl;
}
int main(int argc, char const *argv[]) {
test01();
return 0;
}
6.4 继承中的构造和析构顺序
csharp
#include <iostream>
#include <string>
using namespace std;
// 继承中的对象模型
class Base {
public:
Base() {
cout << "Base Constructor" << endl;
}
int m_A;
protected:
int m_B;
private:
int m_C;
public:
~Base() {
cout << "Base Destructor" << endl;
}
};
class Son : public Base {
public:
Son() {
cout << "Son Constructor" << endl;
}
int m_D;
~Son() {
cout << "Son Destructor" << endl;
}
};
void test01() {
// 继承中的构造和析构顺序
// 先构造父类,再构造子类,析构顺序与构造相反
Son son;
}
int main(int argc, char const *argv[]) {
test01();
return 0;
}
6.5 继承同名成员处理方式
访问子类同名成员 直接访问即可
访问父类同名成员 需要加作用域
csharp
#include <iostream>
#include <string>
using namespace std;
// 继承同名成员处理方式
class Base{
public:
Base(){
m_A = 100;
}
int m_A;
void func(){
cout << "Base func" << endl;
}
void func(int a){
cout << "Base func a: " << a << endl;
}
};
class Son:public Base{
public:
Son(){
m_A = 200;
}
int m_A;
void func(){
cout << "Son func" << endl;
}
};
// 同名成员处理方式
void test01(){
Son son;
cout << son.m_A << endl;
// 如果通过子类对象访问父类同名成员,需要加作用域限定符
cout << son.Base::m_A << endl;
}
// 同名成员函数处理方式
void test02(){
Son son;
son.func();
// 如果通过子类对象访问父类同名成员函数,需要加作用域限定符
son.Base::func();
// 如果子类中出现和父类同名成员函数,子类的同名成员函数会隐藏掉父类所有同名成员函数
// 如果想访问父类中被隐藏的同名成员函数,需要加作用域限定符
son.Base::func(1000);
}
int main(int argc, char const *argv[]) {
test02();
return 0;
}
6.6 继承同名静态成员处理方式
静态成员和非静态成员,处理方式一致
访问子类同名成员 直接访问即可
访问父类同名成员 需要加作用域
csharp
#include <iostream>
#include <string>
using namespace std;
// 继承同名静态成员处理方式
class Base{
public:
static int m_A;
static void func(){
cout << "Base func" << endl;
}
static void func(int a){
cout << "Base func a: " << a << endl;
}
};
int Base::m_A = 100;
class Son:public Base{
public:
static int m_A;
static void func(){
cout << "Son func" << endl;
}
};
int Son::m_A = 200;
// 同名成员处理方式
void test01(){
Son son;
cout << son.m_A << endl;
// 如果通过子类对象访问父类同名成员,需要加作用域限定符
cout << son.Base::m_A << endl;
cout << Son::m_A << endl;
// 第一个:: 代表通过类名方式访问,第二个:: 代表访问父类作用域下
cout << Son::Base::m_A << endl;
}
// 同名成员函数处理方式
void test02(){
Son son;
son.func();
Son::func();
// 如果通过子类对象访问父类同名成员函数,需要加作用域限定符
son.Base::func();
Son::Base::func();
// 如果子类中出现和父类同名成员函数,子类的同名成员函数会隐藏掉父类所有同名成员函数
// 如果想访问父类中被隐藏的同名成员函数,需要加作用域限定符
son.Base::func(1000);
}
int main(int argc, char const *argv[]) {
test02();
return 0;
}
6.7 多继承语法
csharp
#include <iostream>
#include <string>
using namespace std;
// 多继承语法
class Base1 {
public:
Base1() {
m_A = 100;
}
int m_A;
};
class Base2 {
public:
Base2() {
m_A = 200;
}
int m_A;
};
// 多继承语法
// 语法: class 子类 : 继承方式 父类1, 继承方式 父类2...
class Son : public Base1, public Base2 {
public:
Son() {
m_C = 300;
}
int m_C;
int m_D;
};
void test01() {
Son s;
cout << sizeof(s) << endl;
// 当父类出现同名成员变量时,需要加作用域区分
cout << "m_A = " << s.Base1::m_A << endl;
cout << "m_B = " << s.Base2::m_A << endl;
}
int main(int argc, char const *argv[]) {
test01();
return 0;
}
6.7 菱形继承
csharp
#include <iostream>
#include <string>
using namespace std;
// 菱形继承
// 两个派生类继承同一个基类,又有某个类同时继承两个派生类,这种继承称为菱形继承或钻石继承。
class Animal {
public:
int age;
};
// 利用虚继承,解决菱形继承时,数据冗余问题
// 继承之前加上virtual关键字,称为虚继承
// Animal 类称为虚基类
// 羊
class Sheep :virtual public Animal {
};
// 驼类
class Camel :virtual public Animal {
};
// 羊驼
class SheepCamel : public Sheep, public Camel {
};
void test01() {
SheepCamel sc;
sc.Sheep::age = 10;
sc.Camel::age = 20;
// 当菱形继承时,两个派生类共享数据,如果修改数据,会造成二义性,需要加作用域
cout << "sc.Sheep::age = " << sc.Sheep::age << endl;
cout << "sc.Camel::age = " << sc.Camel::age << endl;
cout << "sc.age = " << sc.age << endl;
cout << "sizeof(sc) = " << sizeof(sc) << endl;
// 菱形继承时,会产生两个实例,浪费资源
Sheep s;
s.age = 10;
cout << "s.age = " << s.age << endl;
cout << "sizeof(s) = " << sizeof(s) << endl;
}
int main(int argc, char const *argv[]) {
test01();
return 0;
}