C++学习笔记(十五)

继承

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

有些类与类之间存在特殊的关系,例如下图中:

我们发现,定义这些类时,下级别的成员除了拥有上一级的共性,还有自己的特性。

这个时候我们就可以考虑利用继承的技术,减少重复代码

1. 继承的基本语法

例如我们看到很多的网站中,都有公共的头部、公共的底部、甚至公共的左侧列表,只有中心内容不同,接下来分别使用普通写法和继承写法来实现网页中的内容

普通写法(98行):

#include <iostream>using namespace std;// Java网页
class Java
{
public:void header(){cout << "首页、公开课、登录、注册...(公共头部)" << endl;}void footer(){cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;}void left(){cout << "Java、Python、C++...(公共左侧列表)" << endl;}void content(){cout << "Java视频..." << endl;}
};// Python网页
class Python
{
public:void header(){cout << "首页、公开课、登录、注册...(公共头部)" << endl;}void footer(){cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;}void left(){cout << "Java、Python、C++...(公共左侧列表)" << endl;}void content(){cout << "Python视频..." << endl;}
};// C++网页
class CPP
{
public:void header(){cout << "首页、公开课、登录、注册...(公共头部)" << endl;}void footer(){cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;}void left(){cout << "Java、Python、C++...(公共左侧列表)" << endl;}void content(){cout << "C++视频..." << endl;}
};void test()
{Java ja;ja.header();ja.footer();ja.left();ja.content();cout << "---------------------------------" << endl;Python py;py.header();py.footer();py.left();py.content();cout << "---------------------------------" << endl;CPP cpp;cpp.header();cpp.footer();cpp.left();cpp.content();	
}int main(int argc, char* argv[])
{test();return 0;
}

继承写法(80行):

#include <iostream>using namespace std;// 公共页面
class BasePage
{
public:void header(){cout << "首页、公开课、登录、注册...(公共头部)" << endl;}void footer(){cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;}void left(){cout << "Java、Python、C++...(公共左侧列表)" << endl;}
};// Java网页
class Java :public BasePage
{
public:void content(){cout << "Java视频..." << endl;}
};// Python网页
class Python :public BasePage
{
public:void content(){cout << "Python视频..." << endl;}
};// C++网页
class CPP :public BasePage
{
public:void content(){cout << "C++视频..." << endl;}
};void test()
{Java ja;ja.header();ja.footer();ja.left();ja.content();cout << "---------------------------------" << endl;Python py;py.header();py.footer();py.left();py.content();cout << "---------------------------------" << endl;CPP cpp;cpp.header();cpp.footer();cpp.left();cpp.content();	
}int main(int argc, char* argv[])
{test();return 0;
}

总结:

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

语法:class A :public B

A类  称为子类  也称为  派生类

B类  称为父类  也称为  基类

派生类中的成员,包含两大部分:

一类是从基类继承过来的,一类是自己增加的成员

从基类继承过来的表现其共性,二新增的成员体现了其个性

2. 继承方式

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

继承的方式一种有三种:

1. 公共继承

2. 保护继承

3. 私有继承

3. 继承中的对象模型

父类中的私有成员也是被子类继承下去了,只是由编译器给隐藏后访问不到

利用开发人员命令提示工具查看对象模型

1. 找到要查看的类的文件所在的路径

2. cd到此路径下

3. 查看类的名字和文件的名字

4. cl /d1 reportSingleClassLayout类名 文件名

4. 继承中构造和析构的顺序

子类继承父类后,当创建子类对象,也会调用父类的构造函数

问题:子类和父类的构造和析构顺序是谁先谁后

#include <iostream>using namespace std;class Dad
{
public:Dad(){cout << "父类的构造函数......" << endl;}~Dad(){cout << "父类的析构函数......" << endl;}
};class Son :public Dad
{
public:Son(){cout << "子类的构造函数......" << endl;}~Son(){cout << "子类的析构函数......" << endl;}
};void test()
{Son son;
}int main(int argc, char* argv[])
{test();return 0;
}

总结:继承中 先调用父类的构造函数,再调用子类的构造函数,析构顺序与构造相反

5. 继承同名成员的处理方式

问题:当子类与父类出现同名的成员,如何通过子类对象,访问到子类或者父类中同名的数据呢?

访问子类同名成员 直接访问即可

访问父类同名成员 需要加作用域

#include <iostream>using namespace std;class Dad
{
public:int m_a;Dad(){m_a = 10;}void func(){cout << "Dad中func()的调用..." << endl;}void func(int a){cout << "Dad中func(int a)的调用..." << endl;}
};class Son :public Dad
{
public:int m_a;Son(){m_a = 20;}void func(){cout << "Son中func()的调用..." << endl;}
};void test()
{Son son;cout << son.m_a << endl; // 直接调用 调用的是子类中的同名成员属性cout << son.Dad::m_a << endl; // 调用父类中的同名成员属性需要加作用域son.func(); // 直接调用 调用的是子类中的同名成员函数son.Dad::func(); // 调用父类中的同名成员函数需要加作用域// 如果子类中出现和父类同名的成员函数,子类的同名成员函数会隐藏掉父类中所有同名成员函数// 如果想访问到父类中被隐藏的同名成员函数,需要加作用域son.Dad::func(100);
}int main(int argc, char* argv[])
{test();return 0;
}

总结:

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

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

3. 当子类和父类拥有同名的成员函数,子类会隐藏父类中同名成员函数,加作用域可以访问到父类中同名函数

6. 继承同名静态成员处理方式

问题:继承中同名的静态成员在子类对象上如何进行访问

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

访问子类同名成员 直接访问即可

访问父类同名成员 需要加作用域

#include <iostream>using namespace std;class Dad
{
public:static int m_a;static void func(){cout << "Dad:static void func()" << endl;}static void func(int a){cout << "Dad:static void func(int a)" << endl;}
};
int Dad::m_a = 100;class Son :public Dad
{
public:static int m_a;static void func(){cout << "Son:static void func()" << endl;}
};
int Son::m_a = 200;
void test()
{// 1. 通过对象访问cout << "通过对象访问:" << endl;Son son;cout << "Son中的m_a=" << son.m_a << endl;cout << "Dad中的m_a=" << son.Dad::m_a << endl;// 2. 通过类名访问cout << "通过类名访问:" << endl;cout << "Son中的m_a=" << Son::m_a << endl;// 第一个::代表通过类名方式访问 第二个::代表访问父类作用域下cout << "Dad中的m_a=" << Son::Dad::m_a << endl;// 1. 通过对象访问cout << "通过对象访问:" << endl;son.func();son.Dad::func();son.Dad::func(100);// 2. 通过类名访问Son::func();// 第一个::代表通过类名方式访问 第二个::代表访问父类作用域下Son::Dad::func();Son::Dad::func(100);
}int main(int argc, char* argv[])
{test();return 0;
}

7. 多继承语法

C++允许一个类继承多个类

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

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

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

#include <iostream>using namespace std;class Base1
{
public:int m_a;int m_b;Base1(){m_a = 100;m_b = 200;}
};class Base2
{
public:int m_a;int m_c;Base2(){m_a = 1000;m_c = 300;}
};class Son :public Base1, public Base2
{
public:int m_d;Son(){m_d = 400;}
};void test()
{Son s;cout << "Base1:m_a=" << s.Base1::m_a << endl;cout << "Base2:m_a=" << s.Base2::m_a << endl;cout << "m_b=" << s.m_b << endl;cout << "m_c=" << s.m_c << endl;cout << "m_d=" << s.m_d << endl;
}int main(int argc, char* argv[])
{test();return 0;
}

总结:多继承如果父类中出现了同名的情况,子类使用时需要加作用域

8. 菱形继承

菱形继承概念:

两个派生类继承同一个基类

又有某个类同时继承这两个类

这种继承被称为菱形继承,或者钻石继承

菱形继承的问题:

1. 羊继承了动物的数据,驼也继承了动物的数据,当草泥马使用数据时,就会产生二义性

2. 草泥马继承自动物的数据继承了两份,但其实这份数据只需要一份就可以

#include <iostream>using namespace std;// 动物类
class Animal
{
public:int m_age;
};// 羊类
class Sheep:public Animal{};// 驼类
class Camel:public Animal{};// 羊驼类
class Alpaca :public Sheep, public Camel{};void test()
{Alpaca alpaca;alpaca.Sheep::m_age = 18;alpaca.Camel::m_age = 28;// 当菱形继承时,两个父类拥有相同数据,需要加以作用域进行区分cout << "alpaca.Sheep::m_age = " << alpaca.Sheep::m_age << endl; // 18cout << "alpaca.Camel::m_age = " << alpaca.Camel::m_age << endl; // 28
}int main(int argc, char* argv[])
{test();return 0;
}

这份数据只要一份就可以,菱形继承导致数据有两份,产生资源浪费

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

在继承之前加上关键字virtual变成虚继承

Animal类被称为虚基类

#include <iostream>using namespace std;// 动物类
class Animal
{
public:int m_age;
};// 羊类
class Sheep:virtual public Animal{};// 驼类
class Camel:virtual public Animal{};// 羊驼类
class Alpaca :public Sheep, public Camel{};void test()
{Alpaca alpaca;alpaca.Sheep::m_age = 18;alpaca.Camel::m_age = 28;// 当菱形继承时,两个父类拥有相同数据,需要加以作用域进行区分cout << "alpaca.Sheep::m_age = " << alpaca.Sheep::m_age << endl; // 28cout << "alpaca.Camel::m_age = " << alpaca.Camel::m_age << endl; // 28cout << "m_age = " << alpaca.m_age << endl; // 28
}int main(int argc, char* argv[])
{test();return 0;
}

继承了两份指针,两份指针都指向同一份内容

总结:

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

2. 利用虚继承可以解决菱形继承问题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/234982.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

3 - Electron app BrowserWindow对象-关于窗口

优雅的打开应用~ 当加载缓慢&#xff0c;打开应用的一瞬间会出现白屏&#xff0c;以下方法可以解决 const mainWindow new BrowserWindow({ show: false }) mainWindow.once(ready-to-show, () > {mainWindow.show() }) 设置背景颜色 const win new BrowserWindow({ b…

MongoDB的原子操作findAndReplace、findOneAndDelete和deleteMany

本文主要介绍MongoDB的原子操作findAndReplace、findOneAndDelete和deleteMany。 目录 MongoDB的原子操作一、findAndReplace二、findOneAndDelete三、deleteMany MongoDB的原子操作 MongoDB的原子操作指的是在单个操作中对数据库的数据进行读取和修改&#xff0c;并确保操作是…

selenium css定位

selenium-css定位 element_css driver.find_element(By.CSS_SELECTOR, css表达式)css定位说明 selenium中的css定位&#xff0c;实际是通过css选择器来定位到具体元素&#xff0c;css选择器来自于css语法 css定位优点 语法简洁对比其他定位方式&#xff0c;定位效率更快对…

高防服务器防御靠谱吗?

​  随着互联网的普及和信息技术的不断发展&#xff0c;网络安全问题日益突出。高防服务器作为一种专业的网络安全设备&#xff0c;在防御网络攻击方面扮演着越来越重要的角色。然而&#xff0c;高防服务器是否靠谱&#xff0c;是否能够有效地防御各种网络攻击&#xff0c;一…

CUMT--Java--JDBC编程

目录 一、JDBC简介 二、数据库访问 1、加载数据库驱动 2、建立数据连接 3、创建Statement对象 4、执行SQL语句 5、访问结果集 三、MetaData接口 1、DatabaseMetaData接口 2、ResultSetMetaData接口 四、事务 1、JDBC中的事务 2、保存点 3、批量更新 一、JDBC简…

【JAVA】重力反弹,反弹高次一次比一次低

本来是想实现泡泡屏保(javascript实现漂亮的气泡碰撞效果(Chrome浏览器下更佳) 下载-脚本之家)的&#xff0c;还未实现 import javax.swing.*; import java.awt.*; import java.util.LinkedList; import java.util.Random;class Bubble {public static Image image;public int…

轮滑加盟培训机构管理系统源码开发方案

一、项目背景与目标 &#xff08;一&#xff09;项目背景 随着轮滑运动的普及和市场需求的增加&#xff0c;轮滑加盟培训机构逐渐兴起。这些机构面临着学员管理、课程排班、教师管理等多方面的挑战。为了提高管理效率和服务质量&#xff0c;需要开发一套专门针对轮滑加盟培训…

FormData文件上传多文件上传

一、简介 ​ 通常情况下&#xff0c;前端在使用post请求提交数据的时候&#xff0c;请求都是采用application/json 或 application/x-www-form-urlencoded编码类型&#xff0c;分别是借助JSON字符串来传递参数或者keyvalue格式字符串&#xff08;多参数通过&进行连接&#…

大数据分析22、23真题回忆

2022 学长描述 1. 一个很简单的据估计 2. 算一个决策树 3. Cypher图 4.Hadoop和Spark的区别 2023 真题回忆 1. 大数据分析的定义 说出大数据分析三个层次 2.大数据分析流程 预处理部分包含哪几个步骤 3.Spark核心部件和应用库有哪些 并简要说明功能 4. 主成分分析和因…

HTML5+CSS3小实例:纯CSS实现锚点平滑过渡

实例:纯CSS实现锚点平滑过渡 技术栈:HTML+CSS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"&…

【无语】Microsoft Edge 浏览器不显示后台返回的数值数据

Microsoft Edge 禁用 JSON 视图 写在前面禁用 JSON 视图 写在前面 遇到一个有意思的事情&#xff0c;在用 Microsoft Edge 浏览器发送请求测试时发现&#xff0c;后端返回的数值数据没有正常展示&#xff0c;而是类似查看源码的结果&#xff0c;只显示了一个行号1&#xff0c;…

最优化理论复习--对偶单纯形方法及灵敏度分析

对偶单纯形方法 定义&#xff1a;设 x ( 0 ) x^{(0)} x(0) 是(L)问题的基本解&#xff08;不一定是可行解&#xff08;极点&#xff09;&#xff09;&#xff0c;如果它的对偶问题的解释可行的&#xff0c;则称 x ( 0 ) x^{(0)} x(0) 为原问题的对偶可行基本解 从而衍生出结…

Chappyz 生态迎重磅利好:多链应用程序启动、100% 收入共享计划开启

“首款由人工智能驱动的社区建设工具 Chappyz&#xff0c;即将在 12 月 21 日推出全新的多链平台并向社区开放&#xff0c;同时制定了生态收入 100% 向 Stakers 共享的计划&#xff0c;这不仅是 Chappyz 生态的一个全新进展&#xff0c;也是 Chappyz 生态发展的重磅利好。” 构…

0137 - 跳转控制语句 break、continue、return

文章目录 1 break1.1 基本介绍1.2 基本语法1.3 注意事项和细节说明 2 continue2.1 基本介绍2.2 基本语法 3 return 1 break 1.1 基本介绍 break 语句用于终止某个语句块的执行&#xff0c;一般使用在 switch 或者循环[for , while , do-while]中 1.2 基本语法 { ……break…

新时代体育场馆的未来之路——气膜体育馆

近年来&#xff0c;我国正全面贯彻实施全民健身国家战略&#xff0c;秉持“发展群众体育&#xff0c;服务健康中国”的理念&#xff0c;深入推动群众参与的体育活动&#xff0c;努力实现全民健身与全民健康的深度融合发展。在这一大潮中&#xff0c;体育场馆建设成为业内的一项…

tensorflow入门

一、怎样入手TensorFlow TensorFlow是一个用于机器学习和深度学习的开源框架&#xff0c;它提供了一种灵活的方式来构建和训练神经网络模型。以下是一些TensorFlow框架入门的建议&#xff1a; 学习Python语言&#xff1a;TensorFlow主要使用Python语言进行开发&#xff0c;因此…

欧美电商平台Depop如何入驻?

对标美国二手闲鱼平台Mercia,PoshMark、东南亚Etsy&#xff0c;Depop是英国的一个面向创意人群的二手时尚市场&#xff0c;类似于Instagram&#xff0c;但更专注于买卖二手服装、配饰和艺术品。 有研究显示,由于购物预算减少,高达65%的受访者表示乐意在圣诞节购买或收到二手礼…

JDK bug:ciObjectFactory::create_new_metadata:原因完全解析

文章目录 1、问题2.详细日志2.关键日志3.结论4.JDK&#xff1a;bug最终bug链接&#xff1a; 京东遇到过类似bug各位大佬如果有更详细的解答可以留言。 1、问题 服务不通&#xff0c;接口404&#xff0c;查看日志有一下截图&#xff0c;还有一个更详细的日志 2.详细日志 # #…

cpp_04_类_对象_this指针_常对象_常(成员)函数

1 类 1.1 类的定义 类的作用是抽象事物&#xff08;抽取事物特征&#xff09;的规则。 类的外化表现是用户自定义的复合数据类型&#xff08;包括成员变量、成员函数&#xff09;&#xff1a; 成员变量用于表达事物的属性&#xff0c;成员函数用于表达事物的行为。 类的表现…

智慧食堂餐卡充值文件生成器使用说明

智慧食堂餐卡充值文件生成器 下载地址&#xff1a; https://download.csdn.net/download/boysoft2002/88646277 或者百度网盘下载&#xff1a; https://pan.baidu.com/s/16cxOa5aq0CU0T0xOr2A7-A 操作使用说明 一、文件结构 下载.rar文件后&#xff0c;释放到非系统盘符的…