05-C++ 类和对象-继承

类与对象-03

继承与派生

1. 继承的概念

c++最重要的特征是代码重用,通过继承机制可以利用已有的数据类型,来定义新的数据类型,新的类不仅拥有旧类的成员,还拥有新定义的成员。

一个 B 类继承于 A 类,或称从类 A 派生类 B。这样的话,类 A 成为基类(父类),类 B 成为派生类(子类)。

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

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

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

2. 继承的优点

1)减少重复的代码,减轻程序整体的体量。

2)继承的好处,可以将共性的内容封装成一个基类(父类),遇到专项业务时,可以扩展基类变为一个新类,在新类中重点扩展功能。

3. 继承的语法

class 子类:继承方式 父类名
{ 子类新增自己的数据和方法;
};

4. 继承方式

  • public(推荐):子类将 原封不动的继 承父类成员,但是 不能直接访问 父类 私有的成员

  • protected:子类 继承到 父类的成员 转换为 protected修饰的成员,但是 不能直接访问 父类 私有的成员

  • private:子类将 继承到所有父类成员 转换为 私有的成员,但是 不能直接访问 父类 私有的成员

在这里插入图片描述

示例1:public

#include <iostream>
using namespace std;
class A
{
public:int a;void testA(){cout << "testA" << endl;}
};
class B:public A
{
};
int main(int argc, char *argv[])
{B b;b.a = 10;b.testA();  //testAreturn 0;
}

示例2:protected ,若是protected继承,父类中的public将变为 protected,只能在当前类或子类中使用。

#include <iostream>
using namespace std;
class A
{
public:int a;void testA(){cout << "testA" << endl;}
};
class B:protected A
{
public:void testB(){cout << a << endl;testA();}
};
int main(int argc, char *argv[])
{B b;//此时是protected继承,父类中的public将变为 protected,只能在当前类或子类中使,//所以下面报错//b.a = 10;//报错//b.testA();//报错b.testB(); //93 testAreturn 0;
}

5. 注意

  1. 子类可以继承父类所有成员,但是父类私有成员不可访问
  2. 子类 不能继承父类构造函数拷贝构造析构函数,但是子类中可以调用
  3. 子类可以多继承
  4. 子类在 创建对象 时会 调用父类构造函数,如果 没有明确 写出 调用的父类构造 函数,默认调用 父类无参构造 ,此时如果父类 没有无参构造,程序报错
  5. 子类调用父类构造函数,在 子类构造函数后使用初始化列表方式调用父类构造函数
  6. operator=不能被继承

示例:

#include <iostream>
#include <cstring>
using namespace std;
class Anim{
private:char type[50];int age;char sex[10];
public:Anim(){cout << "Anim无参构造" << endl;}Anim(char *type,char *sex,int age){strcpy(this->type,type);strcpy(this->sex,sex);this->age = age;cout << "Anim有参构造" << endl;}Anim(const Anim& anim){strcpy(this->type,anim.type);strcpy(this->sex,anim.sex);this->age = anim.age;}void setType(char *type){strcpy(this->type,type);}char* getType(){return type;}void setSex(char *sex){strcpy(this->sex,sex);}char* getSex(){return sex;}void setAge(int age){this->age = age;}int getAge(){return age;}
};
class A{};
//3、子类可以多继承
class Yang:public Anim,public A
{
public:Yang(){}//5、初始化列表调用父类构造函数Yang(char *type,char *sex,int age):Anim(type,sex,age){}
};int main(int argc, char *argv[])
{//Yang y;//1、子类可以继承父类所有成员,但是父类私有成员不可访问//y.age;//2、子类不能继承父类的构造函数,拷贝构造,析构函数//Yang y("绵羊","公",18); //Anim有参构造//4、创建子类对象时会调用父类构造函数//默认调用父类无参构造//Yang y;//如果子类构造函数在初始化列表中指定调用父类的构造函数//那么就不会默认调用父类无参构造//Yang y("山羊","公",3);//如果父类中没有无参构造,子类没有明确写出调用父类构造函数//此时子类将调用父类无参构造,但是父类没有无参构造//程序报错Yang y;return 0;
}

6. 构造与析构的执行顺序

继承中的构造和析构:

  • 子类对象在创建时会首先调用父类的构造函数
  • 父类构造函数执行完毕后,才会调用子类的构造函数
  • 当父类构造函数有参数时,需要在子类初始化列表(参数列表)中显示调用父类构造函数
  • 析构函数调用顺序和构造函数相反

在这里插入图片描述

示例1:子类继承父类

#include <iostream>using namespace std;
class A{
public:A(){cout << "A的构造函数" << endl;}~A(){cout << "A的析构函数" << endl;}
};
class B:public A{
public:B(){cout << "B的构造函数" << endl;}~B(){cout << "B的析构函数" << endl;}
};
int main(int argc, char *argv[])
{B b;return 0;
}
//A的构造函数
//B的构造函数
//B的析构函数
//A的析构函数

示例2:子类继承父类,该子类中还要其他类的成员

#include <iostream>using namespace std;
class A{
public:A(){cout << "A的构造函数" << endl;}~A(){cout << "A的析构函数" << endl;}
};
class C{
public:C(){cout << "C的构造函数" << endl;}~C(){cout << "C的析构函数" << endl;}
};
class B:public A{
private:C c;
public:B(){cout << "B的构造函数" << endl;}~B(){cout << "B的析构函数" << endl;}
};
int main(int argc, char *argv[])
{B b;return 0;
}
//A的构造函数
//C的构造函数
//B的构造函数
//B的析构函数
//C的析构函数
//A的析构函数

7. 继承中父子类成员重名

7.1 成员变量重名

调用方式:

  • 操作子类成员变量:子类对象.成员变量名
  • 操作父类提供的成员变量:子类对象.父类名::成员变量名

示例:

#include <iostream>using namespace std;
class Basic{
public:int x;int y;Basic(int x):x(x){}
};
class Son:public Basic{
public:int x;//子类构造函数中必须调用父类构造函数//默认调用父类无参构造Son(int x1, int x2):Basic(x1){this->x = x2;}
};int main(int argc, char *argv[])
{Son son(10,100);//当父子类成员变量重名时//此时子类对象中有两个名称相同的变量//1个是继承父类的//1个是子类特有的//获取子类特有的该变量cout << son.x << endl;//100//获取父类提供的x变量cout << son.Basic::x << endl;//10//没有重名的成员直接获取cout << son.y << endl; //随机数return 0;
}
7.2 成员函数重名

概念:

  • 子类成员函数名父类成员函数名 重名,此时 子类该函数就是对父类名为该函数名的函数进行 重定义
  • 重定义
    • 继承关系中
    • 子类函数名与父类函数名相同
  • 特点:屏蔽父类该函数

调用方式:

  • 操作子类成员 函数:子类对象.成员函数名(实参列表)
  • 操作父类提供的成员函数:子类对象.父类名::成员函数名(实参列表)

示例:

#include <iostream>using namespace std;
class Fu{
public:void test(){cout << "fu test()" << endl;}void test(int a){cout << "fu test(int)" << endl;}void test(int a, int b){cout << "fu test(int, int)" << endl;}void fun01(){cout << "fu fun01()" << endl;}
};
class Zi:public Fu{
public:void test(){cout << "zi test()" << endl;}
};int main(int argc, char *argv[])
{Zi zi;//当父子类函数名重名时//子类调用重名函数,默认调用的是子类自己的函数zi.test();      //zi test()//子类调用继承于父类的 重名函数zi.Fu::test();  //fu test()zi.Fu::test(1);  //fu test(int)zi.Fu::test(10,20);  //fu test(int, int)//子类调用继承于父类的 非重名函数zi.fun01();     //fu fun01()return 0;
}

8. 多继承

概念:一个子类继承与 多个父类

语法:

class 子类名:继承方式1 父类1, 继承方式2 父类2, ...
{子类特有成员
}

父类构造顺序:

  • 子类对象创建时,按继承 编写的顺序 依次执行父类对象构造,与子类构造函数后初始化列表中的顺序无关

示例1:

#include <iostream>using namespace std;
class A{
public:int x;A(int a):x(a){}
};
class B{
public:int x;B(int a):x(a){}
};
class C:public A,public B
{
public:int x;C(int a,int b,int c):x(a),A(b),B(c){}
};
int main(int argc, char *argv[])
{C c(1,2,3);//获取c类中的xcout << c.x << endl;    //1//获取c类中继承与A类的xcout << c.A::x << endl; //2//获取c类中继承与B类的xcout << c.B::x << endl; //3return 0;
}

示例2:

#include <iostream>using namespace std;
class A{public:A(){cout << "A的构造函数" << endl;}~A(){cout << "A的析构函数" << endl;}};
class B{public:B(){cout << "B的构造函数" << endl;}~B(){cout << "B的析构函数" << endl;}
};
class C:public B,public A{public:C():A(),B(){cout << "C的构造函数" << endl;}~C(){cout << "C的析构函数" << endl;}
};
int main(int argc, char *argv[])
{C c;return 0;
}
//B的构造函数
//A的构造函数
//C的构造函数
//C的析构函数
//A的析构函数
//B的析构函数

9. 菱形继承(了解)

概念:

A的子类A1与A2B类多继承A1与A2类此时这种关系称为菱形继承

注意:

  • 菱形继承会导致子类用于多份祖先数据,当孙子类调用成员(函数或数据)时,会产生二义性。
  • 如:
    • A类中提供num成员变量
    • A1与A2类属于A的子类,,那么A1与A2类将各自拥有一份num
    • B作为A1与A2的子类,那么 B将拥有两个num

在这里插入图片描述

示例:

#include <iostream>
#include <cstring>
using namespace std;
class Anim{
public:char name[50];Anim(char *name){strcpy(this->name, name);}
};
class Yang:public Anim{
public:Yang(char *name):Anim(name){}
};
class Tuo:public Anim{
public:Tuo(char *name):Anim(name){}
};
class YangTuo:public Yang, public Tuo{
public:YangTuo(char *name01, char *name02):Yang(name01),Tuo(name02){}
};
int main(int argc, char *argv[])
{YangTuo yt("tom", "jerry");cout << yt.Yang::name << endl;  //tomcout << yt.Tuo::name << endl;   //jerrycout << &(yt.Yang::name) << endl;   //0x61fe2ccout << &(yt.Tuo::name) << endl;    //0x61fe5ereturn 0;
}

菱形继承类布局:

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

10. 虚继承

概念:使用 virtual修饰继承关系

语法:

class 子类名:virtual 继承关系 父类名
{};

解决问题:

解决菱形继承的调用二义性,多个类只保存一份相同数据

如:

  • A类中提供num成员变量
  • A1与A2类属于A的子类,那么A1与A2类将各自拥有一份num
  • B作为A1与A2的子类,那么B将拥有两个num,此时调用num会出现二义性
  • 所以只能虚继承使其存储一个num.

示例:

#include <iostream>
#include <cstring>
using namespace std;
class Anim{
public:char name[50];Anim(char *name){strcpy(this->name, name);}
};
class Yang:virtual public Anim{
public:Yang(char *name):Anim(name){}
};
class Tuo:virtual public Anim{
public:Tuo(char *name):Anim(name){}
};
class YangTuo:public Yang, public Tuo{
public:YangTuo(char *name01, char *name02):Anim(name01),Yang(name01),Tuo(name02){}
};int main(int argc, char *argv[])
{YangTuo yt("tom", "jerry");cout << yt.Yang::name << endl;  //tomcout << yt.Tuo::name << endl;   //tomcout << &(yt.Yang::name) << endl;   //0x61fe5ccout << &(yt.Tuo::name) << endl;    //0x61fe5creturn 0;
}

虚继承类布局:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

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

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

相关文章

数字人私人定制

数字人是什么&#xff1f; 在回答这个问题之前&#xff0c;我们先回答另一个问题&#xff0c;人如何与人工智能交流&#xff1f;目前可以通过文字、语音、电脑屏幕、手机屏幕、平板、虚拟现实设备等和人工智能交流&#xff0c;为了得到更好的交流体验&#xff0c;人工智能必然…

php 8.4 xdebug扩展编译安装方法

最新版php8.4 xdebug扩展只能通过编译方式安装, pecl是安装不了的, 编译方法如下 下载最新版xdebug git clone https://github.com/xdebug/xdebug.git 却换入xdebug目录执行编译安装xdebug cd xdebug phpize./configure --enable-xdebugmakemake install3. 配置启用xdebug 这…

使用element中el-cascader级联选择器实现省市区街道筛选(非动态加载)

<template><el-form ref"form" :model"form" label-width"80px"><el-form-item label"地址:" prop"addressList"><el-cascaderv-model"form.addressList":props"props":options&q…

Pandas教程(一)—— 数据结构

前言 Pandas是贯穿数据分析的主要工具之一&#xff0c;它经常和其他数值计算工具一起使用&#xff08;例如&#xff1a;Numpy、SciPy和matplotlib&#xff09;。尽管pandas采用了很多NumPy的代码风格&#xff0c;但二者最大的区别是&#xff1a;pandas主要用于处理表格型或异质…

GBASE南大通用-GBase 8s数据库日志模式及切换

一、 GBase 8s数据库共有以下 4 种日志模式&#xff1a;无日志模式、缓冲日志模式、无缓冲日志模式、ANSI 模式。详细介绍如下&#xff1a; 1、无日志模式&#xff08;Non logging&#xff09;&#xff1a; 采用无日志模式时&#xff0c;所有 DML 操作都不会被记录到日志中&…

IP地理位置定位技术基本原理

IP地理位置定位技术的基本原理是基于IP地址的特性。每个IP地址在网络中都有一个与之对应的地理位置信息&#xff0c;这是通过IP地址数据库来确定的。这个数据库由ISP&#xff08;Internet Service Provider&#xff09;或其它一些机构维护&#xff0c;其中包含了每个IP地址的地…

链表精选题集

目录 1 链表翻转 题目链接&#xff1a; 解题&#xff1a; 试错版&#xff1a; 2 找中间节点 题目链接: 题解&#xff1a; 3 找倒数第k个节点 题目链接&#xff1a; 题解&#xff1a; 4 将两个升序链表合并为一个升序链表 题目链接&#xff1a; 题解&#xff1a; …

tmux 包的介绍及使用

tmux 本博文参照 https://blog.csdn.net/qq_43912191/article/details/123214679 对 tmux 进行总结和归纳。 tmux&#xff08;Terminal Multiplexer&#xff09;是一款命令行下的终端复用软件&#xff0c;用于在一个终端窗口中运行多个终端会话&#xff0c;并且可以在各会话之…

第六课:冷战和消费主义、个人计算机革命、图形用户界面(GUI)及3D图形

第六课&#xff1a;冷战和消费主义、个人计算机革命、图形用户界面&#xff08;GUI&#xff09;及3D图形 第二十四章&#xff1a;冷战和消费主义本课概括&#xff1a;政府和消费者推动了计算机的发展 第二十五章&#xff1a;个人计算机革命本集概括&#xff1a;继续讲计算机发展…

AJAX: 整理2:学习原生的AJAX,这边借助express框架

1. npm install express 终端直接安装 2. 测试案例&#xff1a;Hello World&#xff01; 新建一个express.js的文件&#xff0c;写入下方的内容 // 1. 引入express const express require(express)// 2. 创建服务器 const app express()// 3.创建路由规则 // request 是对请…

mxxWechatBot微信机器人V2版本文档说明

大家伙&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂。 先看这里 一、前言二、mxxWechatBot流程图三、怎么使用&#xff1f; 一、前言 经过不断地探索与研究&#xff0c;mxxWechatBot正式上线&#xff0c;届时全面开放使用。 mxxWechatBot&am…

【动态规划精选题目】3、简单多状态模型

此动态规划系列主要讲解大约10个系列【后续持续更新】 本篇讲解简单多状态模型中的9道经典题&#xff0c;会在讲解题目同时给出AC代码 目录 1、按摩师 2、力扣198:打家劫舍1 3、打家劫舍II 4、删除并获得点数 5、 粉刷房子 6、力扣309:买卖股票的最佳时机含冷冻期 7、 买…

【数据库系统概论】第7章-数据库设计

文章目录 7.1 数据库设计概述7.2 需求分析7.2.1 需求分析的任务7.2.2 需求分析的难点7.2.2 需求分析的方法7.2.3 数据字典 7.3 概念结构设计7.3.1 概念模型7.3.2 E-R模型7.3.3 概念结构设计 7.4 逻辑结构设计7.4.1 E-R图向关系模型的转换7.4.2 数据模型的优化7.4.3 设计用户子模…

【教程】标注工具Labelimg的安装与使用

图片标注主要是为了建立自己的数据集&#xff0c;便于进行更深度的学习训练。本篇文章将对一款十分好用的图片标注工具labelimg进行介绍&#xff0c;重点介绍其安装以及使用的过程。 - 什么是labelimg labelimg 是一个可视化的图像标定工具。它是用Python编写的&#xff0c;并…

HDFS客户端UnknownHostException事故解析

文章目录 前言事故现场问题分析是否是整个域名解析服务当时都出问题了是否是出问题的pods本身的域名解析有问题 异常发生的全部过程域名的解析是什么时候发生的&#xff0c;怎么发生的域名解析的详细流程 重试发生在什么地方为什么重试会无效 Bugfix代码详解关于StandardHostRe…

特殊权限(suid sticky acl mask)

1.suid 1. 普通用户可不可以修改密码&#xff1f; 答&#xff1a;是可以的&#xff0c;可以修改自己的密码 2. /etc/shadow 文件的作用是什么&#xff1f; 答&#xff1a;存储用户密码的文件 3. 普通用户是否可以修改/etc/shadow 文件&#xff1f; 答&#xff1a;不可以&…

STM32+Codesys工业软件PLC解决方案

工业控制系统在现代制造和自动化领域扮演着关键角色, 基于IEC 61131-3 标准的控制器编程开发软件平台CODESYS&#xff0c;适用于多种行业的控制系统的开发,使用户方便快捷地对自动化工程进行编程和配置&#xff0c;完成项目开发、软件测试和应用调试。 本次STM32联合合作伙伴C…

服务器运行状况监控工具

服务器运行状况监视提供了每个服务器状态和性能的广泛概述&#xff0c;通过监控服务器指标&#xff0c;如 CPU 使用率、内存消耗、I/O、磁盘使用率、进程等&#xff0c;服务器运行状况监控可以避免服务器停机。 服务器性能监控指标 服务器是网络中最重要的组件之一&#xff0…

计算机网络复习6

应用层 文章目录 应用层网络应用模型域名系统DNS文件传输协议FTP电子邮件万维网 网络应用模型 客户/服务器模型 客户/服务器&#xff08;Client/Server&#xff0c;C/S)模型中&#xff0c;有一个总是打开的主机称为服务器&#xff0c;它服务于许多来自其他称为客户机的主机请求…

Java集合/泛型篇----第一篇

系列文章目录 文章目录 系列文章目录前言一、ArrayList和linkedList的区别二、HashMap和HashTable的区别三、Collection包结构,与Collections的区别四、泛型常用特点前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站…