C++ 10 类与对象(继承)
创始人
2025-06-01 01:37:01
0

一、继承简介

① 继承是面向对象的三大特性之一。

② 定义类时,下级别的成员除了拥有上一级的共性,还有自己的特性。这个时候,就可以考虑利用继承技术,减少重复代码。

1.1 普通实现

#include 
using namespace std;
#include//打印输出类
class Java
{
public:void header(){cout << "首页、公开课、登陆、注册...(公共头部)" << endl;}void footer(){cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;}void left(){cout << "Java、Python、C++....(公共分类列表)" << endl;}void content(){cout << "Java学科视频" << endl;}
};class Python
{
public:void header(){cout << "首页、公开课、登陆、注册...(公共头部)" << endl;}void footer(){cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;}void left(){cout << "Java、Python、C++....(公共分类列表)" << endl;}void content(){cout << "Python学科视频" << endl;}
};class CPP
{
public:void header(){cout << "首页、公开课、登陆、注册...(公共头部)" << endl;}void footer(){cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;}void left(){cout << "Java、Python、C++....(公共分类列表)" << endl;}void content(){cout << "C++学科视频" << endl;}
};void test01()
{cout << "Java下载视频页面如下:" << endl;Java ja;ja.header();ja.footer();ja.left();ja.content();cout << "........................" << endl;cout << "Python下载视频页面如下:" << endl;Python py;py.header();py.footer();py.left();py.content();cout << "........................" << endl;cout << "C++下载视频页面如下:" << endl;CPP cpp;cpp.header();cpp.footer();cpp.left();cpp.content();
}int main()
{test01();system("pause");return 0;}运行结果:Java下载视频页面如下:
首页、公开课、登陆、注册...(公共头部)
帮助中心、交流合作、站内地图...(公共底部)
Java、Python、C++....(公共分类列表)
Java学科视频
........................
Python下载视频页面如下:
首页、公开课、登陆、注册...(公共头部)
帮助中心、交流合作、站内地图...(公共底部)
Java、Python、C++....(公共分类列表)
Python学科视频
........................
C++下载视频页面如下:
首页、公开课、登陆、注册...(公共头部)
帮助中心、交流合作、站内地图...(公共底部)
Java、Python、C++....(公共分类列表)
C++学科视频
请按任意键继续. . .

1.2 继承实现

继承的好处:减少重复代码

 语法:class 子类:继承方式 父类

// 子类 也称为 派生类

// 父类 也称为 基类

#include 
using namespace std;
#include//打印输出类
class BasePage
{
public:void header(){cout << "首页、公开课、登陆、注册...(公共头部)" << endl;}void footer(){cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;}void left(){cout << "Java、Python、C++....(公共分类列表)" << endl;}
};// 继承的好处:减少重复代码
// 语法:class 子类:继承方式 父类
// 子类 也称为 派生类
// 父类 也称为 基类//Java页面
class Java:public BasePage   //继承了BasePage,把BasePage里面的内容全部拿到手了
{
public:void content(){cout << "Java学科视频" << endl;}
};//Python页面
class Python :public BasePage   //继承了BasePage,把BasePage里面的内容全部拿到手了
{
public:void content(){cout << "Python学科视频" << endl;}
};//C++页面
class CPP :public BasePage   //继承了BasePage,把BasePage里面的内容全部拿到手了
{
public:void content(){cout << "CPP学科视频" << endl;}
};void test01()
{cout << "Java下载视频页面如下:" << endl;Java ja;ja.header();ja.footer();ja.left();ja.content();cout << "........................" << endl;cout << "Python下载视频页面如下:" << endl;Python py;py.header();py.footer();py.left();py.content();cout << "........................" << endl;cout << "C++下载视频页面如下:" << endl;CPP cpp;cpp.header();cpp.footer();cpp.left();cpp.content();
}int main()
{test01();system("pause");return 0;}运行结果:Java下载视频页面如下:
首页、公开课、登陆、注册...(公共头部)
帮助中心、交流合作、站内地图...(公共底部)
Java、Python、C++....(公共分类列表)
Java学科视频
........................
Python下载视频页面如下:
首页、公开课、登陆、注册...(公共头部)
帮助中心、交流合作、站内地图...(公共底部)
Java、Python、C++....(公共分类列表)
Python学科视频
........................
C++下载视频页面如下:
首页、公开课、登陆、注册...(公共头部)
帮助中心、交流合作、站内地图...(公共底部)
Java、Python、C++....(公共分类列表)
CPP学科视频
请按任意键继续. . .

二、三种继承改变权限

① 继承的语法:class 子类:继承方式 父类

② 继承方式一共有三种:

  1. 公共继承
  2. 保护继承
  3. 私有继承

③ 不同的继承方式,父类中的变量被继承后,权限相应的得到了改变,如下图所示。

- 父类中的私有属性,子类不管用哪种继承方式都不可以访问

- 如果是公共继承,父类中公共/保护/私有属性,在子类中依然是公共/保护/私有属性

- 如果是保护继承,父类中公共/保护/私有属性,在子类中变为保护属性

- 如果是私有继承,父类中公共/保护/私有属性,在子类中变为私有属性

#include 
using namespace std;
#include//打印输出类
class Base1
{
public:int m_A;
protected:int m_B;
private:int m_C;
};//公共继承
class Son1:public Base1
{
public:void func(){m_A = 10; //父类中的公共权限成员 到子类中依然是公共权限m_B = 10; //父类中的保护权限成员 到子类中依然是保护权限//m_C = 10; //父类中的私有权限成员 子类访问不到}
};void test01()
{Son1 s1;s1.m_A = 100;  //公共权限,类内能访问,类外也能访问//s1.m_B = 100;  //保护权限,类内能访问,类外不能访问
}//保护继承
class Son2:protected Base1
{
public:void func(){m_A = 10; //父类中的公共权限成员 到子类中变为保护权限m_B = 10; //父类中的保护权限成员 到子类中依然是保护权限//m_C = 10; //父类中的私有权限成员 子类访问不到}
};void test02()
{Son2 s2;//s2.m_A = 100;  //保护权限,类内能访问,类外不能访问//s2.m_B = 100;  //保护权限,类内能访问,类外不能访问
}//私有继承
class Son3:private Base1
{
public:void func(){m_A = 10; //父类中的公共权限成员 到子类中变为私有权限m_B = 10; //父类中的保护权限成员 到子类中变为私有权限//m_C = 10; //父类中的私有权限成员 子类访问不到}
};void test03()
{Son3 s3;//s3.m_A = 100;  //私有权限,类内能访问,类外不能访问//s3.m_B = 100;  //私有权限,类内能访问,类外不能访问
}int main()
{system("pause");return 0;}

三、继承对象内存

3.1 查询继承对象所占内存

#include 
using namespace std;
#include//继承中的对象模型class Base
{
public:int m_A;
protected:int m_B;
private:int m_C;
};//公共继承
class Son:public Base
{int m_D; 
};//利用开发人员命令提示工具查看对象模型
//跳转盘符→F:
//跳转文件路径→cd 具体路径下
//查看命令
//cl /d1 reportSingleClassLayout查看的类名 "文件名"void test01()
{//父类中所有非静态成员属性都会被子类继承下去//父类中私有成员属性 是被编译器给隐藏了,因此是访问不到,但是确实被继承下去了cout << "size of Son =" << sizeof(Son) << endl;  //16个字节,父类3个int一个12个字节,字节1个int4个字节                        
}int main()
{test01();system("pause");return 0;}运行结果:size of Son =16
按任意键继续. . .

3.2 VS自带开发工具查询

① 首先打开visio studio的开发人员命令工具,如下图所示。

四、继承构造和析构顺序

① 继承中,先调用父类构造函数,再调用子类构造函数,析构顺序与构造顺序相反,先调用子类析构函数,再调用父类析构函数。

#include 
using namespace std;
#include//继承中的构造和析构顺序class Base
{
public:Base(){cout << "Base构造函数!" << endl;}~Base(){cout << "Base析构函数!" << endl;}
};//
class Son:public Base
{
public:Son(){cout << "Son构造函数!" << endl;}~Son(){cout << "Son析构函数!" << endl;}
};void test01()
{//Base b;  //创建父类对象只有父类的构造函数、析构函数//继承中的构造和析构顺序如下://先构造父类、再构造子类,析构的顺序与构造的顺序相反Son s;
}int main()
{test01();system("pause");return 0;}运行结果:Base构造函数!
Son构造函数!
Son析构函数!
Base析构函数!
请按任意键继续. . .

五、同名成员处理

① 子类对象可以直接访问到子类中同名成员。

② 子类对象加作用域可以访问到父类同名成员。

③ 当子类与父类拥有同名的成员函数,子类会隐藏父类中所有同名成员函数(有参、无参),加作用域才可以访问到父类中同名函数。

#include 
using namespace std;
#include//继承中同名成员处理class Base
{
public:Base(){m_A = 100;}int m_A;void func(){cout << "Base - func()调用" << endl;}void func(int a){cout << "Base - func(int a)调用" << endl;}
};class Son:public Base
{
public:Son(){m_A = 200;}void func(){cout << "Son - func()调用" << endl;}int m_A;
};//同名成员属性处理方式
void test01()
{Son s;cout << "Son 下 m_A=" << s.m_A << endl;//如果通过子类对象访问到父类中同名成员,需要加作用域cout << "Base 下 m_A=" << s.Base::m_A << endl;  }//同名成员函数处理方式
void test02()
{Son s;s.func(); //直接调用 调用时子类中的同名成员//调用父类中同名成员函数s.Base::func();//如果子类中出现和父类同名的成员函数,子类的同名成员会隐藏掉父类中所有同名成员函数//如果想访问到父类中被隐藏的同名成员函数,需要加作用域s.Base::func(100);
}//同名成员函数处理
int main()
{test01();test02();system("pause");return 0;}运行结果:Son 下 m_A=200
Base 下 m_A=100
Son - func()调用
Base - func()调用
Base - func(int a)调用
请按任意键继续. . .

6. 同名静态成员处理

① 静态成员和非静态成员出现同名,处理方式一致:

  1. 访问子类同名成员,直接访问
  2. 访问父类同名成员,需要加作用域

② 加上static关键字后,成员发生变化,成员变成静态成员。

③ 静态成员变量特点:

  1. 所有对象都共享同一份数据。
  2. 编译阶段就分配内存。
  3. 类内声明,类外初始化。

④ 静态成员函数特点:

  1. 只能访问静态成员变量,不能访问非静态成员变量。
  2. 所有对象都共享同一份函数实例。
#include 
using namespace std;//继承中同名静态成员处理方式
class Base
{
public:static int m_A;  //静态成员类内声明,类外初始化static void func(){cout << "Base - static func()" << endl;}static void func(int a){cout << "Base - static func(int a)" << endl;}
};int Base::m_A=100;class Son:public Base
{
public:static int m_A;static void func(){cout << "Son - static void func()" << endl;}
};int Son::m_A = 200;//同名静态成员属性
void test01()
{//1、通过对象访问Son s;cout << "Son 下 m_A = " << s.m_A << endl;cout << "Base 下 m_A = " << s.Base::m_A << endl;//2、通过类名访问cout << "Son 下 m_A = "<< Son::m_A << endl;//第一个::代表通过类名方式访问  第二个::代表访问父类作用域cout << "Base 下 m_A= "<< Son::Base::m_A << endl;  
}void test02()
{//1、通过对象访问Son s;s.func();s.Base::func();//2、通过类名访问Son::func();Son::Base::func();//子类出现和父类同名静态成员函数,也会隐藏掉父类中所有同名成员函数//如何想访问父类中被隐藏同名成员,需要加作用域Son::Base::func(100);
}//同名成员函数处理
int main()
{test01();test02();system("pause");return 0;}运行结果:Son 下 m_A = 200
Base 下 m_A = 100
Son 下 m_A = 200
Base 下 m_A= 100
Son - static void func()
Base - static func()
Son - static void func()
Base - static func()
Base - static func(int a)
请按任意键继续. . .

7. 多继承语法

① C++运行一个类继承多个类。

② 语法:class 子类:继承方式 父类1,继承方式 父类2,.....

③ 多继承可能会引发父类中有同名成员出现,需要加作用域区分。

④ C++实际开发中不建议用多继承。

#include 
using namespace std;class Base1
{
public:Base1(){m_A = 100;}int m_A;};class Base2
{
public:Base2(){m_A = 200;}int m_A;};//子类  需要继承Base1和Base2
//语法:class 子类:继承方式 父类1,继承方式 父类2,.....
class Son:public Base1,public Base2
{
public:Son(){m_C = 300;m_D = 400;}int m_C;int m_D;
};void test01()
{Son s;cout << "sizeof(Son):" << sizeof(s) << endl;//当父类中出现同名成员,需要加作用域区分cout << "Base1::m_A = " << s.Base1::m_A << endl;cout << "Base2::m_A = " << s.Base2::m_A << endl;}int main()
{test01();system("pause");return 0;}运行结果:sizeof(Son):16
Base1::m_A = 100
Base2::m_A = 200
请按任意键继续. . .

8. 菱形继承

8.1 菱形继承简介

① 菱形继承概念:

  1. 两个派生类继承同一个基类
  2. 又有某个类同时继承两个派生类
  3. 这种继承被称为菱形继承

② 羊继承了动物的数据,驼同样继承了动物的数据,当草泥马使用数据是,就会产生二义性。

③ 草泥马继承自动物的数据继承了两份,其实我们应当清楚,这份数据我们只需要一份就可以。

④ 菱形继承带来的主要问题是子类继承两份相同的数据,导致资源浪费以及毫无意义。

⑤ 利用虚继承可以解决菱形继承问题。

8.2 菱形继承普通方式 

#include 
using namespace std;//动物类
class Animal
{
public:int m_Age;
};//羊类
class Sheep:public Animal{};//驼类
class Tuo:public Animal{};//羊驼类
class SheepTuo:public Sheep,public Tuo{};void test01()
{SheepTuo st;st.Sheep::m_Age = 18;st.Tuo::m_Age = 28;//当出现菱形继承,两个父类拥有相同数据,需要加以作用域区分cout << "st.Sheep::m_Age="<< st.Sheep::m_Age << endl;cout << "st.Tuo::m_Age=" << st.Tuo::m_Age << endl;//这份数据我们知道 只有一份就可以,菱形继承导致数据有两份,资源浪费
}int main()
{test01();system("pause");return 0;
}运行结果:st.Sheep::m_Age=18
st.Tuo::m_Age=28
请按任意键继续. . .

8.3 菱形继承虚继承

8.3.1 菱形继承虚继承方式

#include 
using namespace std;//动物类
class Animal
{
public:int m_Age;
};//利用虚继承 解决菱形继承的问题
//继承之前 加上关键字 virtual 变成 虚继承
//虚继承后,Animal类 称为 虚基类//羊类
class Sheep:virtual public Animal{};//驼类
class Tuo:virtual public Animal{};//羊驼类
class SheepTuo:public Sheep,public Tuo{};void test01()
{SheepTuo st;st.Sheep::m_Age = 18;st.Tuo::m_Age = 28;//当出现菱形继承,两个父类拥有相同数据,需要加以作用域区分cout << "st.Sheep::m_Age="<< st.Sheep::m_Age << endl;cout << "st.Tuo::m_Age=" << st.Tuo::m_Age << endl;//虚继承,多产生一种输出方式(因为上面两个是同一份数据,所以可以不加作用域来区分了)cout << "st.m_Age=" << st.m_Age << endl;
}int main()
{test01();system("pause");return 0;
}运行结果:st.Sheep::m_Age=28
st.Tuo::m_Age=28
st.m_Age=28
请按任意键继续. . .

8.3.2 菱形继承虚继承VS查询

① Sheep类和Tuo类继承的都是vbptr,vbptr为虚基类继承指针。

  1. v - virtual
  2. b - base
  3. ptr = pointer

② 菱形继承并不是继承两份数据,而是继承两份指针,这两个指针会分别指向虚基类表,虚基类表中会记录偏移量,加上这个偏移量,会指向这个唯一的数据。

上一篇:Opengl ES之文字渲染

下一篇:MySQL架构

相关内容

热门资讯

南京开放“以债换房”政策,可直... ⇧点蓝色字关注“互联网联合辟谣平台” 近日,有“南京二手房零首付李经理”“合肥瑶珺房地产代理有限公司...
一公司骗享约61万,被罚885... 近日,国家税务总局重庆市税务局公布两起骗享税费优惠政策典型案件,分别是重庆百子讯科技有限公司违规享受...
罗志恒:财政政策不应受3%赤字... 罗志恒 系粤开证券首席经济学家、中国首席经济学家论坛理事 自2008年以来,本轮积极财政政策实行了长...
原创 曼... 阿提哈德球场的角旗。 一位足球财务专家公布了他对曼城队针对英超联赛的 FFP 案件的最新判决,可能面...
还得加钱!利物浦报价维尔茨再遭... 北京时间6月2日消息,据德国媒体报道称,利物浦求购维尔茨的第二份报价遭到勒沃库森拒绝,药厂坚持要价1...
罗马诺:欧冠决赛的0-5惨败,... 直播吧6月2日讯 欧冠决赛,国际米兰0-5完败巴黎圣日耳曼,无缘冠军。据转会名记罗马诺透露,本场失利...
刚刚!港股下挫,A50跌超2%... 每经编辑|何小桃 受全球关税负面信息的打击,6月2日上午,亚太股市几乎全线下跌。 截至发稿,恒生...
原创 权... 作者:吕东平 摘要 在全球化与文明对话日益深入的今天,某些国家仍呈现出权力结构对法治原则的系统性侵...
分手后男子起诉按现金价折算金饰... 近日,宁夏同心县人民法院公布一起案例,2024年9月,宝某与周某经人介绍相识并按照习俗结婚,宝某依习...