C++ ——继承

体现的是代码复用的思想

1、子类继承父类,子类就拥有了父类的特性(成员方法和成员属性)

2、已存在的类被称为“基类”或者“父类”或者“超类”;新创建的类被称为“派生类”或者“子类”

注意:

        (1)子类继承了父类,子类就拥有了父类的属性和方法

        (2)如果子类重写了父类的同名方法,子类对象默认调用的是子类自己的成员方法,如果想调用父类的同名方法,要添加父类作用域限定符

#include <iostream>
using namespace std;
class Father{
public:
    int num1=88;
    int num2=99;
public:
    //成员方法
    void show()const{
        cout<<"num1="<<num1<<",num2="<<num2<<endl;
    }
    void cook(){
        cout<<"做水煮鱼"<<endl;
    }
};
class Son:public Father{  //public:放在继承的地方,表示继承方式是公有继承
public:
    void sing(){
        cout<<"唱歌"<<endl;
    }
    void cook(){
        cout<<"做红烧肉"<<endl;
    }
};
int main(){
    Son s1;
    s1.cook();  //默认子类调用的是自己的成员方法
    s1.show();
    s1.sing();
    s1.Father::cook();  //子类可以使用添加父类作用域限定符,来调用父类的同名方法
    return 0;
}

1、构造函数

1.1 派生类的构造函数

继承中的无参构造函数

(1)基类(父类)中的构造函数不能被继承

(2)派生类(子类)中必须要调用基类中的构造函数来完成属性的初始化

(3)默认情况下,编译器会自动在派生类中调用父类的无参构造函数

(4)子类继承了父类,子类独有的属性需要在自己的构造函数进行初始化,而子类从父类继承过来的属性,必须通过子类构造函数调用父类构造函数进行初始化

#include <iostream>
using namespace std;
class Father{
public:
    int num1=88;
    int num2=99;
public:
    //编译器默认的无参构造函数
    Father(){}
    //有参构造函数
    Father(int num1,int num2)
        :num1(num1),num2(num2){}
};
class Son:public Father{  //public:放在继承的地方,表示继承方式是公有继承
public:
    int a;
public:
    //编译器默认的子类无参调用父类无参构造函数
    Son():Father(){}
    //子类有参构造函数调用父类有参构造函数,来完成继承下来的属性的初始化
    Son(int num1,int num2,int a):Father(num1,num2),a(a){}
};
int main(){
    Son s2(10,55,66);
//    s2.show();
    cout<<s2.a<<endl;  //66
    return 0;
}

1.2 派生类调用基类构造函数

(1)目的:因为构造函数和析构函数,不能继承,所以派生类的构造函数通过调用基类的构造函数完成部分属性的初始化

(2)派生类的构造函数调用基类的构造函数的方式:透传构造、委托构造、继承构造

1.2.1 透传构造

派生类的构造函数直接调用基类的构造函数

class Father{
public:
    int num;
public:
    //无参构造函数---->委托构造
    Father():Father(90){}
    //有参构造函数
    Father(int num)
        :num(num){}
};
class Son:public Father{  //public:放在继承的地方,表示继承方式是公有继承
public:
    int num1;
public:
    //委托构造
    Son():Son(2,88){}
    //透传构造
    Son(int num1,int num):Father(num),num1(num1){}
};

1.2.2 委托构造

可维护性好,但效率相对较低

思想:一个类中的构造函数是可以调用这个类中的其他构造函数

父类的无参构造函数调用父类的有参构造函数;子类的无参构造函数调用子类的有参构造函数;子类的有参构造函数透传父类的有参构造函数

注意:委托构造离不开透传构造

class Father{
public:
    int num;
public:
    //无参构造函数---->委托构造
    Father():Father(90){}
    //有参构造函数
    Father(int num)
        :num(num){}
};
class Son:public Father{  //public:放在继承的地方,表示继承方式是公有继承
public:
    int num1;
public:
    //委托构造
    Son():Son(2,88){}
    //透传构造
    Son(int num1,int num):Father(num),num1(num1){}
};

1.2.3 继承构造

透传构造的简写方式,一句话自动实现透传构造,编译器会自动给派生类添加n个构造函数(n取决于基类中构造函数的个数),并实现自动透传其基类构造函数

class Father{
public:
    int num;
    int age;
    string addr;
public:
    //无参构造函数---->委托构造
    Father():Father(90){}
    //有参构造函数
    Father(int num)
        :num(num){}
    Father(int age,string addr)
        :age(age),addr(addr){}
};
class Son:public Father{  //public:放在继承的地方,表示继承方式是公有继承
public:
    int num1=99;
public:
    //继承构造
    using Father::Father;
};

2、对象的构建和销毁的过程

(1)成员对象:类中有一个成员,该成员是对象类型,叫做对象成员

                先调用成员对象的构造函数,再调用自己的构造函数;析构函数则相反

(2)父子类继承时

                先调用父类的构造函数,再调用子类的构造函数;析构函数则相反

(3)静态成员对象:类中有一个静态成员,该成员是一个对象类型

                静态成员对象的构造函数先执行,再执行自己的构造函数;析构函数则相反

顺序:

        构造函数:静态成员对象---->成员对象---->父类---->子类

        析构函数:子类---->父类---->成员对象---->静态成员对象

2.1 成员对象

class Demon{
public:
    //构造函数
    Demon(){
        cout<<"成员对象的构造函数"<<endl;
    }
    ~Demon(){
        cout<<"成员对象的析构函数"<<endl;
    }
};
class Test{
public:
    Test(){
        cout<<"构造函数"<<endl;
    }
    ~Test(){
        cout<<"析构函数"<<endl;
    }
};

2.2 父子类继承时

class Father{
public:
    Father(){
        cout<<"父类构造"<<endl;
    }
    ~Father(){
        cout<<"父类析构"<<endl;
    }
};
class Son:public Father{
public:
    Son():Father(){
        cout<<"子类构造"<<endl;
    }
    ~Son(){
        cout<<"子类析构"<<endl;
    }
};

2.3 静态成员对象

class P{
public:
    P(){
        cout<<"静态成员对象的构造"<<endl;
    }
    ~P(){
        cout<<"静态成员对象的析构"<<endl;
    }
};
class Phone{
public:
    //类内声明
    static P p1;  //静态成员变量的声明
    Phone(){
        cout<<"构造函数"<<endl;
    }
    ~Phone(){
        cout<<"析构函数"<<endl;
    }
};
P Phone::p1=P();  //类外初始化

3、权限 

3.1 权限修饰符

C++中成员的权限修饰符有3种:

        (1)public:共有的        类内、子类内、类外可以访问

        (2)private:私有的        只能类内访问

        (3)protected:受保护的        类内、子类内可以访问

注意:如果权限修饰符可以省略,默认是private

#include <iostream>
using namespace std;
class Father{
public:
    int num1;
private:
    int num2;
protected:
    int num3;
public:
    //构造函数
    Father(int num1,int num2,int num3)
        :num1(num1),num2(num2),num3(num3){}
    void show()const{
        cout<<this->num1<<" ";  //public 类内可以访问
        cout<<this->num2<<" ";  //private 类内可以访问
        cout<<this->num3<<" ";  //protected  类内可以访问
        cout<<"*******"<<endl;
    }
};
class Son:public Father{
public:
    using Father::Father;
    void fun()const{
        cout<<this->num1<<" "<<this->Father::num1<<" ";  //public 子类内可以访问
        cout<<this->num3<<" "<<this->Father::num3<<" ";  //protected  子类内可以访问
        cout<<"*******"<<endl;
    }
};
int main(){
    Father f1(1,2,3);
    f1.show();
    Son s1(4,5,6);
    s1.fun();
    cout<<s1.num1<<endl;  //public 类外可以访问
    return 0;
}

3.2 继承方式

3.2.1 public(共有继承)

(1)父类是public---->子类也是public

(2)父类是protected---->子类也是protected

(3)父类是private---->子类也是private,但是类内不可以直接访问,可以间接访问

#include <iostream>
using namespace std;
class Father{
public:
    int num1;
protected:
    int num2;
private:
    int num3;
public:
    Father(int num1,int num2,int num3)
        :num1(num1),num2(num2),num3(num3){}
    void fun()const{}
    int get_num3()const{
        return num3;
    }
};
class Son:public Father{
public:
    Son(int num1,int num2,int num3)
        :Father(num1,num2,num3){}
    void show(){
        cout<<this->num1<<endl;  //父类public---->子类也是public,类内可以访问
        cout<<this->num2<<endl;  //父类protected---->子类也是protected
//        cout<<this->num3<<endl;  //报错,父类private---->子类也是private,但是类内不可以直接访问
        cout<<this->Father::get_num3()<<endl;  //父类private---->子类也是private,可以间接访问
        cout<<"******"<<endl;
    }
};
class Sunzi:public Son{
public:
    Sunzi(int num1,int num2,int num3)
        :Son(num1,num2,num3){}
    void fun()const{
        cout<<this->num1<<" "<<this->Son::num1<<endl;  //父类public---->子类也是public,派生类内可以访问
        cout<<this->num2<<" "<<this->Son::num2<<endl;  //父类protected---->子类也是protected
        cout<<"******"<<endl;
    }
};
int main(){
    Son s1(1,2,3);
    s1.show();
    cout<<s1.num1<<endl;  //父类public---->子类也是public,类外可以访问
    Sunzi sz(4,5,6);
    sz.fun();
    return 0;
}

3.2.2 protected(受保护的继承)

(1)父类是public---->子类是protected

(2)父类是protected---->子类也是protected

(3)父类是private---->子类也是private,但是类内不可以直接访问,可以间接访问

#include <iostream>
using namespace std;
class Father{
public:
    int num1;
protected:
    int num2;
private:
    int num3;
public:
    Father(int num1,int num2,int num3)
        :num1(num1),num2(num2),num3(num3){}
    void fun()const{}
    int get_num3()const{
        return num3;
    }
};
class Son:protected Father{
public:
    Son(int num1,int num2,int num3)
        :Father(num1,num2,num3){}
    void show(){
        cout<<this->num1<<endl;  //父类public---->子类是protected
        cout<<this->num2<<endl;  //父类protected---->子类也是protected
//        cout<<this->num3<<endl;  //报错,父类private---->子类也是private,但是类内不可以直接访问
        cout<<this->Father::get_num3()<<endl;  //父类private---->子类也是private,可以间接访问
        cout<<"******"<<endl;
    }
};
class Sunzi:protected Son{
public:
    Sunzi(int num1,int num2,int num3)
        :Son(num1,num2,num3){}
    void fun()const{
        cout<<this->num1<<" "<<this->Son::num1<<endl;  //父类public---->子类是protected
        cout<<this->num2<<" "<<this->Son::num2<<endl;  //父类protected---->子类也是protected
        cout<<"******"<<endl;
    }
};
int main(){
    Son s1(1,2,3);
    s1.show();
    Sunzi sz(4,5,6);
    sz.fun();
    return 0;
}

3.2.3 private(私有继承)

(1)父类是public---->子类是private,类内可以直接访问

(2)父类是protected---->子类是private,类内可以直接访问

(3)父类是private---->子类也是private,但是类内不可以直接访问,可以间接访问

4、多重继承

4.1 概念

继承中,允许有多个基类,每一个基类的继承都可以看作是唯一的独一继承,此时派生类就拥有了所有基类的特性

#include <iostream>
using namespace std;
class Sofa{
public:
    int num=1;
public:
    void job(){
        cout<<"沙发可以坐"<<endl;
    }
};
class Bed{
public:
    void work(){
        cout<<"床可以躺"<<endl;
    }
};
class SofsBed:public Sofa,public Bed{
public:
    void work(){
        cout<<"即可以躺又可以坐"<<endl;
    }
};
int main(){
    SofsBed sfb;
    sfb.job();
    sfb.work();
    cout<<sfb.num<<endl;
    sfb.Bed::work();
    return 0;
}

问题:多个基类同时拥有同名成员函数,此时派生类对象直接调用该函数会产生歧义

解决方法:添加基类作用域限定符

4.2 菱形继承

多继承中的若干个基类,又同时拥有同一个基类,此时叫菱形继承(钻石继承)

#include <iostream>
using namespace std;
//爷爷类
class Furniture{
public:
    void show(){
        cout<<"我们是家具"<<endl;
    }
};
//基类
class Sofa:virtual public Furniture{};
class Bed:virtual public Furniture{};
//派生类
class SofsBed:public Sofa,public Bed{};
int main(){
    SofsBed sfb;
//    sfb.show();  //报错,问题:两个基类拥有了同名函数,产生了歧义
    //解决方法1:使用基类作用域限定符
    sfb.Bed::show();
    sfb.Sofa::show();
    //解决方法2:使用虚继承
    /*继承方式有两种:普通继承(默认的)和虚继承(继承方式前添加virtual关键字)*/
    sfb.show();
    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【排版教程】如何在Word/WPS中优雅的插入参考文献

材料展示 随便选取一段综述内容&#xff0c;以及对应的参考文献&#xff0c;如下图所示&#xff1a; 1 参考文献编辑 首先对参考文献部分进行编辑&#xff0c;将其设置自动编号 在段落中&#xff0c;选择悬挂缩进 在编号中&#xff0c;设置自定义编号&#xff0c;然后按照…

STM32 看门狗

目录 背景 独立看门狗&#xff08;IWDG&#xff09; 寄存器访问保护 窗口看门狗&#xff08;WWDG&#xff09; 程序 独立看门狗 设置独立看门狗程序 第一步、使能对独立看门狗寄存器的写操作 第二步、设置预分频和重装载值 第三步、喂狗 第四步、使能独立看门狗 喂狗…

【第二节】C++设计模式(创建型模式)-抽象工厂模式

目录 引言 一、抽象工厂模式概述 二、抽象工厂模式的应用 三、抽象工厂模式的适用场景 四、抽象工厂模式的优缺点 五、总结 引言 抽象工厂设计模式是一种创建型设计模式&#xff0c;旨在解决一系列相互依赖对象的创建问题。它与工厂方法模式密切相关&#xff0c;但在应用…

docker基操

docker基操 首先就是安装docker使用docker:创建容器-制作一个镜像-加载镜像首先就是安装docker 随便找一个教程安装就可以,安装过程中主要是不能访问谷歌,下面这篇文章写了镜像的一些问题: 安装docker的网络问题 使用docker:创建容器-制作一个镜像-加载镜像 主要是参考:这篇…

3D打印注塑件-省模具费90%的解决方案

"开模费用50万&#xff0c;首批订单才200件&#xff1f;" 这是许多制造企业的真实困境。传统注塑工艺动辄数周的开模周期和5-50万元的模具成本&#xff0c;让中小企业的产品迭代举步维艰。 在传统制造流程中&#xff0c;注塑件的生产往往需要高昂的模具开发费用和较…

Java+SpringBoot+Vue+数据可视化的综合健身管理平台(程序+论文+讲解+安装+调试+售后)

感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望帮助更多的人。 系统介绍 在当今社会&#xff0c;随着人们生活水平的不断提高和健康意识的日益增强&#xff0c;健…

美的楼宇科技基于阿里云 EMR Serverless Spark 构建 LakeHouse 湖仓数据平台

作者&#xff1a;美的楼宇科技事业部 先行研究中心智能技术部 美的楼宇科技 IoT 数据平台建设背景 美的楼宇科技事业部&#xff08;以下简称楼宇科技&#xff09;是美的集团旗下五大板块之一&#xff0c;产品覆盖多联机组、大型冷水机组、单元机、机房空调、扶梯、直梯、货梯…

matlab 车辆进出检测算法设计GUI界面-论文

1、内容简介 matlab151-车辆进出检测算法设计GUI界面-论文 可以交流、咨询、答疑 2、内容说明 略 随着科学技术的进步&#xff0c;社会的发展&#xff0c;各行各业都在发生着巨大的变化。近段时间以来&#xff0c;“无人化”智能产业正处于一个风口阶段&#xff0c;似乎我们…

python学习书籍推荐

### Python 学习路线图概述 为了有效地掌握Python这门编程语言并应用于不同领域&#xff0c;构建一个合理的学习路径至关重要。此学习路径不仅涵盖了基础语法&#xff0c;还深入到特定应用方向的关键技术。 #### 基础阶段 在这个初始阶段&#xff0c;重点在于理解Python的基…

基于Spring Boot的农事管理系统设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

在 Ansys Motion 中创建链式伸缩臂的分步指南

介绍 链传动在负载和/或运动要远距离传递的机器中非常多产&#xff0c;例如&#xff0c;在两个平行轴之间。链条驱动系统的设计需要了解载荷传递和运动学如何影响链条张力、轴轴承中的悬臂载荷、轴应力和运动质量等。使用 Ansys Motion&#xff0c;可以轻松回答上述所有问题以…

Web Scraper,强大的浏览器爬虫插件!

Web Scraper是一款功能丰富的浏览器扩展爬虫工具&#xff0c;有着直观的图形界面&#xff0c;无需编写代码即可自定义数据抓取规则&#xff0c;高效地从网页中提取结构化数据&#xff0c;而且它支持灵活的数据导出选项&#xff0c;广泛应用于电商监控、内容聚合、市场调研等多元…

数据结构:栈和队列详解(下)

目录 一.如何用队列实现栈 1.思路&#xff1a; 2.具体代码&#xff1a; 二.如何用栈实现队列 1.思路&#xff1a; 2.具体代码&#xff1a; 一.如何用队列实现栈 原题来源&#xff1a;https://leetcode.cn/problems/implement-stack-using-queues/description/ 前言&#xf…

DeepSeek智能测试知识库助手PRO版:多格式支持+性能优化

前言 测试工程师在管理测试资产时,需要面对多种文档格式、大量文件分类及知识库的构建任务。为了解决这些问题,我们升级了 DeepSeek智能测试知识库助手,不仅支持更多文档格式,还加入了 多线程并发处理 和 可扩展格式支持,大幅提升处理性能和灵活性。 主要功能亮点: 多格…

宝塔面板开始ssl后,使用域名访问不了后台管理

宝塔面板后台开启ssl访问后&#xff0c;用的证书是其他第三方颁发的证书 再使用 域名/xxx 的形式&#xff1a;https://域名:xxx/xxx 访问后台&#xff0c;结果出现如下&#xff0c;不管使用 http 还是 https 的路径访问都进不后台管理 这个时候可以使用 https://ip/xxx 的方式来…

机器学习_12 逻辑回归知识点总结

逻辑回归是机器学习中一种重要的分类算法&#xff0c;广泛应用于二分类和多分类问题。它不仅能够预测分类结果&#xff0c;还能提供每个类别的概率估计。今天&#xff0c;我们就来深入探讨逻辑回归的原理、实现和应用。 一、逻辑回归的基本概念 1.1 逻辑回归与线性回归的区别…

AI Agent实战:打造京东广告主的超级助手 | 京东零售技术实践

前言 自2022年末ChatGPT的问世&#xff0c;大语言模型&#xff08;LLM&#xff09;技术引发全球关注。在大模型技术落地的最佳实践中&#xff0c;智能体&#xff08;Agent&#xff09;架构显现出巨大潜力&#xff0c;成为业界的普遍共识&#xff0c;各大公司也纷纷启动Agent技…

【工具篇】【深度解析 DeepAI 工具:开启 AI 应用新体验】

一、DeepAI 基本信息 嘿,咱先来说说 DeepAI 这工具到底是啥。DeepAI 是一个综合性的人工智能平台,就像是一个装满各种 AI 魔法的百宝箱。它把好多先进的人工智能技术整合到一起,让咱们普通人也能轻松用上这些高大上的 AI 功能。 这个平台背后有一群超厉害的技术人员,他们…

C语言之typedef

目录 前言 一、基本数据类型定义 二、作用 自带阅读 封装复杂类型的描述过程 三、指针类型定义 ​ 四、函数类型定义 总结 前言 typedef是C语言中用来为已有数据类型取别名的关键字。通过使用typedef关键字&#xff0c;可以方便地为数据类型定义新的名称&#xff0c;提高代码的…

如何在 SpringBoot 项目使用 Redis 的 Pipeline 功能

本文是博主在批量存储聊天中用户状态和登陆信息到 Redis 缓存中时&#xff0c;使用到了 Pipeline 功能&#xff0c;并对此做出了整理。 一、Redis Pipeline 是什么 Redis 的 Pipeline 功能可以显著提升 Redis 操作的性能&#xff0c;性能提升的原因在于可以批量执行命令。当我…