当前位置: 首页 > news >正文

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;
}

相关文章:

C++ ——继承

体现的是代码复用的思想 1、子类继承父类&#xff0c;子类就拥有了父类的特性&#xff08;成员方法和成员属性&#xff09; 2、已存在的类被称为“基类”或者“父类”或者“超类”&#xff1b;新创建的类被称为“派生类”或者“子类” 注意&#xff1a; &#xff08;1&#…...

LeetCode 热题 100 283. 移动零

LeetCode 热题 100 | 283. 移动零 大家好&#xff0c;今天我们来解决一道经典的算法题——移动零。这道题在LeetCode上被标记为简单难度&#xff0c;要求我们将数组中的所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。下面我将详细讲解解题思路&#xff0c;…...

游戏引擎学习第116天

回顾昨天的工作 本次工作内容主要集中在游戏开发的低级编程优化&#xff0c;尤其是手动优化软件渲染。工作目的之一是鼓励开发者避免依赖外部库&#xff0c;而是深入理解代码并进行优化。当前阶段正进行SIMD&#xff08;单指令多数据&#xff09;优化&#xff0c;使用Intel推荐…...

react(9)-redux

使用CRA快速创建react项目 npx create-react-app react-redux 安装配套工具 npm i reduxjs/toolkit react-redux 启动项目 在创建项目时候会出现一个问题 You are running create-react-app 5.0.0, which is behind the latest release (5.0.1). We no longer support…...

Linux内核实时机制7 - 实时改造机理 - 软中断优化下

Linux内核实时机制7 - 实时改造机理 - 软中断优化下 https://blog.csdn.net/u010971180/article/details/145722641以下分别以Linux4.19、Linux5.4、Linux5.10、Linux5.15 展开分析,深入社区实时改造机理的软中断优化过程。https://blog.csdn.net/weixin_41028621/article/det…...

企业知识管理平台重构数字时代知识体系与智能服务网络

内容概要 现代企业知识管理平台的演进呈现出全生命周期管理与智能服务网络构建的双重特征。通过四库体系&#xff08;知识采集库、加工库、应用库、评估库&#xff09;的协同运作&#xff0c;该系统实现了从知识沉淀、结构化处理到价值释放的完整闭环。其中&#xff0c;知识图…...

大数据组件(四)快速入门实时数据湖存储系统Apache Paimon(3)

Paimon的下载及安装&#xff0c;并且了解了主键表的引擎以及changelog-producer的含义参考&#xff1a; 大数据组件(四)快速入门实时数据湖存储系统Apache Paimon(1) 利用Paimon表做lookup join&#xff0c;集成mysql cdc等参考&#xff1a; 大数据组件(四)快速入门实时数据…...

SVN把英文换中文

原文链接&#xff1a;SVN设置成中文版本 都是英文&#xff0c;换中文 Tortoise SVN 安装汉化教程(乌龟SVN) https://pan.quark.cn/s/cb6f2eee3f90 下载中文包...

Ubuntu 的RabbitMQ安装

目录 1.安装Erlang 查看erlang版本 退出命令 2. 安装 RabbitMQ 3.确认安装结果 4.安装RabbitMQ管理界面 5.启动服务并访问 1.启动服务 2.查看服务状态 3.通过IP:port 访问界面 4.添加管理员用户 a&#xff09;添加用户名&#xff1a;admin&#xff0c;密码&#xff1…...

基于WebRTC与AI大模型接入EasyRTC:打造轻量级、高实时、强互动的嵌入式音视频解决方案

随着物联网和嵌入式技术的快速发展&#xff0c;嵌入式设备对实时音视频通信的需求日益增长。然而&#xff0c;传统的音视频解决方案往往存在体积庞大、实时性差、互动体验不佳等问题&#xff0c;难以满足嵌入式设备的资源限制和应用场景需求。 针对以上痛点&#xff0c;本文将介…...

QML 实现一个动态的启动界面

QML 实现一个动态的启动界面 一、效果查看二、源码分享三、所用到的资源下载 一、效果查看 二、源码分享 工程结构 main.qml import QtQuick import QtQuick.Controls import QtQuick.Dialogs import Qt.labs.platformWindow {id:windowwidth: 640height: 400visible: truetit…...

智能预警系统标准化处理流程

在当今数字化时代,IT系统的稳定运行对企业的业务连续性至关重要。为了及时发现和响应系统异常,构建智能预警系统已成为许多企业的当务之急。但仅仅拥有预警系统还不够,我们还需要一套标准化的处理流程,确保问题能够高效、有序地得到解决。 © ivwdcwso (ID: u012172506) 一…...

Unity游戏制作中的C#基础(4)数组声明和使用

一、数组的声明 在 C# 中&#xff0c;声明数组有多种方式&#xff0c;每种方式都有其适用的场景&#xff0c;下面为你逐一详细介绍&#xff1a; 1. 直接初始化声明 这种方式直观且便捷&#xff0c;在声明数组的同时就为其赋初值&#xff0c;让数组从诞生之初就拥有了具体的数据…...

tailwindcss学习03

01 入门 02 vue中接入 03 工具类优先 准备 vue.svg <svg viewBox"0 0 40 40" xmlns"http://www.w3.org/2000/svg"> <defs> <linearGradient x1"50%" y1"0%" x2"50%" y2"100%" id"a"&…...

QML Component 与 Loader 结合动态加载组件

在实际项目中&#xff0c;有时候我们写好一个组件&#xff0c;但不是立即加载出来&#xff0c;而是触发某些条件后才动态的加载显示出来&#xff0c;当处理完某些操作后&#xff0c;再次将其关闭掉&#xff1b; 这样的需求&#xff0c;可以使用 Component 包裹着组件&#xff…...

Visual studio 2022 将打开文件的方式由单击改为双击

1. 打开vs2022&#xff0c;选择Tools -> Options打开Options设置页面 2. 在左侧依次展开Environment, 选择Tabs and Windows 3. 在右侧面板往下拖拽滚动条&#xff0c;找到Preview Tab section, unchecked "Preview selected files in Solution Explorer (Altclick t…...

网络工程师 (49)UDP协议

前言 UDP协议&#xff0c;即用户数据报协议&#xff08;User Datagram Protocol&#xff09;&#xff0c;是一种无连接的、不可靠的、面向报文的传输层通信协议。 一、基本特点 无连接性&#xff1a;UDP在发送数据之前不需要与目标设备建立连接&#xff0c;也无需在数据发送结束…...

了解大数据

一、大数据的特点&#xff1a; 1.大量 2.高速 3.多样 结构化数据和非结构化数据 4.低价值密度 二、大数据的应用场景&#xff1a;视频推荐、电商推荐等 三、大数据的技术发展脉络 阶段1&#xff1a;单机时代 阶段2&#xff1a;大数据时代-分布式处理 阶段3&#xff1a;实…...

命令模式

1. 命令模式简介 命令模式(Command Pattern)是一种行为型设计模式,它将一个请求封装为一个对象,从而使您可以用不同的请求对客户进行参数化、对请求排队或记录请求日志,以及支持可撤销的操作。命令模式的核心思想是将操作和操作的执行者解耦,使得操作可以独立于执行者进…...

解放大脑!用DeepSeek自动生成PPT!

DeepSeek应用&#xff08;PPT篇&#xff09; DeepSeek作为当前最好的AI大模型之一&#xff0c;其强大的文本生成能力被广泛的应用于各个领域&#xff0c;本文我们来聊聊用DeepSeek来自动生成PPT。 一、DeepSeek & PPT DeepSeek本身没有直接生成PPT的能力&#xff0c;换个…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...