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

C++类基础(十七)

类的继承——补充知识
● public 与 private 继承(C++ Public, Protected and Private Inheritance)

改变了类所继承的成员的访问权限

//公有继承
struct Base
{
public:int x;
private:int y;
protected:int z;
};
struct Derive : public Base //公有继承基类
{
/*public:int x;
protected:int z;*/void fun(){x = 10; //可以访问,公有继承基类后,基类中的公有成员在派生类中的访问权限仍然是公有成员y = 11; //不可访问,无论哪种继承基类,基类的私有成员只能在基类中访问 Error: 'y' is a private member of 'Base'z = 12; //可以访问,公有继承基类后,基类中的保护成员在派生类中的访问权限仍然是保护成员}
};
struct Derive2 : public Derive //公有继承派生类
{void fun(){x = 10; //可以访问,公有继承派生类后,基类中的公有成员在派生类的派生类中的访问权限仍然是公有成员y = 11; //不可访问,无论哪种继承派生类,基类的私有成员只能在基类中访问 Error: 'y' is a private member of 'Base'z = 12; //可以访问,公有继承派生类后,基类中的保护成员在派生类的派生类中的访问权限仍然是保护成员}
};
int main()
{Base val;val.x; //类外可以访问该类的公有成员val.y; //类外不能访问该类的私有成员, Error: 'y' is a private member of 'Base'val.z; //类外不能访问该类的保护成员, Error: 'z' is a protected member of 'Base'Derive d;d.x; //派生类对象可以在类外访问基类的公有成员d.y; //派生类对象不可在类外访问基类的私有成员,Error: 'y' is a private member of 'Base'd.z; //派生类对象不可在类外访问基类的保护成员,Error: 'z' is a protected member of 'Base'Derive2 d2;d2.x; //派生类的派生类对象可以在类外访问基类的公有成员d2.y; //派生类的派生类对象不可在类外访问基类的私有成员,Error: 'y' is a private member of 'Base'd2.z; //派生类的派生类对象不可在类外访问基类的保护成员,Error: 'z' is a protected member of 'Base'
}
//保护继承
struct Base
{
public:int x;
private:int y;
protected:int z;
};
struct Derive : protected Base //保护继承基类
{
/*protected:int x;
protected:int z;*/void fun(){x = 10; //可以访问,保护继承基类后,基类中的保护成员在派生类中的访问权限成为保护成员y = 11; //不可访问,无论哪种继承基类,基类的私有成员只能在基类中访问 Error: 'y' is a private member of 'Base'z = 12; //可以访问,保护继承基类后,基类中的保护成员在派生类中的访问权限仍然是保护成员}
};
struct Derive2 : public Derive //公有继承派生类
{void fun(){x = 10; //可以访问,公有继承派生类后,基类中的公有成员在经过派生类的保护继承后变成保护成员,在派生类的派生类中仍是保护成员y = 11; //不可访问,无论哪种继承派生类,基类的私有成员只能在基类中访问 Error: 'y' is a private member of 'Base'z = 12; //可以访问,公有继承派生类后,基类中的保护成员在派生类的派生类中的访问权限仍然是保护成员}
};
int main()
{Base val;val.x; //类外可以访问该类的公有成员val.y; //类外不能访问该类的私有成员, Error: 'y' is a private member of 'Base'val.z; //类外不能访问该类的保护成员, Error: 'z' is a protected member of 'Base'Derive d;d.x; //基类中的公有成员在经过派生类的保护继承后变成派生类的保护成员,派生类对象不可在类外访问自己的保护成员,Error: 'x' is a protected member of 'Base'd.y; //派生类对象不可在类外访问基类的私有成员,Error: 'y' is a private member of 'Base'd.z; //保护继承对基类的保护成员的访问权限无影响,派生类对象不可在类外访问基类的保护成员,Error: 'z' is a protected member of 'Base'Derive2 d2;d2.x; //基类中的公有成员在经过派生类的保护继承后变成派生类的保护成员,派生类的派生类对象不可在类外访问该保护成员,Error: 'x' is a protected member of 'Base'd2.y; //派生类的派生类对象不可在类外访问基类的私有成员,Error: 'y' is a private member of 'Base'd2.z; //保护继承对基类的保护成员的访问权限无影响,派生类的派生类对象不可在类外访问该保护成员,Error: 'z' is a protected member of 'Base'
}
//私有继承
struct Base
{
public:int x;
private:int y;
protected:int z;
};
struct Derive : private Base //私有继承基类
{
/*private:int x;
private:int z;*/void fun(){x = 10; //可以访问,私有继承基类后,基类中的保护成员在派生类中的访问权限成为私有成员y = 11; //不可访问,无论哪种继承基类,基类的私有成员只能在基类中访问 Error: 'y' is a private member of 'Base'z = 12; //可以访问,私有继承基类后,基类中的保护成员在派生类中的访问权限成为私有成员}
};
struct Derive2 : public Derive //公有继承派生类
{void fun(){x = 10; //不可访问,公有继承派生类后,基类中的公有成员在经过派生类的私有继承后变成私有成员,在派生类的派生类中已不可见,Error: 'x' is a private member of 'Base'y = 11; //不可访问,无论哪种继承派生类,基类的私有成员只能在基类中访问,Error: 'y' is a private member of 'Base'z = 12; //不可访问,公有继承派生类后,基类中的保护成员在经过派生类的私有继承后变成私有成员,在派生类的派生类中已不可见,Error: 'z' is a private member of 'Base'}
};
int main()
{Base val;val.x; //类外可以访问该类的公有成员val.y; //类外不能访问该类的私有成员, Error: 'y' is a private member of 'Base'val.z; //类外不能访问该类的保护成员, Error: 'z' is a protected member of 'Base'Derive d;d.x; //基类中的公有成员在经过派生类的私有继承后变成派生类的私有成员,派生类对象不可在类外访问自己的私有成员,Error: 'x' is a private member of 'Base'd.y; //派生类对象不可在类外访问基类的私有成员,Error: 'y' is a private member of 'Base'd.z; //基类中的保护成员在经过派生类的私有继承后变成派生类的私有成员,派生类对象不可在类外访问自己的私有成员,Error: 'z' is a private member of 'Base'Derive2 d2;d2.x; //基类中的公有成员在经过派生类的保继承后变成派生类的私有成员,派生类的派生类对象不可在类外访问该私有成员,Error: 'x' is a private member of 'Base'd2.y; //派生类的派生类对象不可在类外访问基类的私有成员,Error: 'y' is a private member of 'Base'd2.z; //基类中的保护成员在经过派生类的私有继承后变成派生类的私有成员,派生类的派生类对象不可在类外访问该私有成员,Error: 'z' is a private member of 'Base'
}

– public 继承:描述 是一个 的关系 “ ”
– private 继承:描述 根据基类实现出 的关系 “ ”
– protected 继承:几乎不会使用
● using 与继承
– 使用 using 改变基类成员的访问权限
● 派生类可以访问该成员

struct Base
{
public:int x = 10;
private:int y = 20;
protected:int z = 30;
};
struct Derive : Base
{
public:using Base::z; //在派生类中使用using改变了基类成员的访问权限,using只能改变在派生类中可见的基类成员的访问权限(即公有成员和保护成员)using Base::y; //基类的私有成员在基类外都是不可见的,因此不能使用using改变基类私有成员的访问权限, Error: 'y' is a private member of 'Base'
};
int main()
{Derive d;std::cout << d.x << '\n'; //Of course OKstd::cout << d.z << '\n'; //OK
}

● 无法改变构造函数的访问权限

struct Base
{
protected:Base(int) {}
};
struct Derive : Base
{
public:using Base::Base; //Error: 'Base(int)' is protected within this context
};
struct Base
{
protected:void fun(){std::cout << "void fun()\n";}void fun(int input){std::cout << "void fun(int input): " << input << '\n';}void fun(char ch){std::cout << "void fun(char ch): " << ch << '\n';}
};
struct Derive : Base
{
public:using Base::fun; //同时改变基类中重载的三个fun()的权限
};
int main()
{Derive d;d.fun(); //OKd.fun(3); //OKd.fun('a'); //OK
}

在这里插入图片描述

struct Base
{
protected:void fun(){std::cout << "void Base::fun()\n";}void go(){std::cout << "void Base::go()\n";}
};
struct Derive : private Base
{
public:using Base::fun; //私有继承后,Base::fun()在派生类中成为私有成员,使用using改变其成为公有成员void go2(){std::cout << "void Derive::go2()\n";go();}
};
int main()
{Derive d;d.fun();d.go2();
}

在这里插入图片描述
– 使用 using 继承基类的构造函数逻辑

struct Base
{
public:Base(int) //公有成员{std::cout << "Base(int)\n";}
};
struct Derive : Base
{
public:using Base::Base;
};
int main()
{Derive d(10);
}

在这里插入图片描述

struct Base
{
public:Base(int){std::cout << "Base(int)\n";}
};
struct Derive : Base
{
public:Derive(int x): Base(x) //对基类构造函数的增删改会影响到派生类构造函数的增删改,维护极其不便{}using Base::Base; //使用using
};

– using 与部分重写

struct Base
{
protected:virtual void fun(){std::cout << "virtual void fun()\n";}virtual void fun(int){std::cout << "virtual void fun(int)\n";}
};
struct Derive : Base
{
public:using Base::fun;
};
int main()
{Derive d;d.fun();d.fun(100);
}

在这里插入图片描述

struct Base
{
protected:virtual void fun(){std::cout << "virtual void Base::fun()\n";}virtual void fun(int){std::cout << "virtual void Base::fun(int)\n";}
};
struct Derive : Base
{
public:using Base::fun;void fun(int) override{std::cout << "void Derive::fun(int) override\n";}
};
int main()
{Derive d;d.fun();d.fun(100);
}

在这里插入图片描述

struct Base
{
protected:Base(int) = default; //保护成员,Error: Only special member functions may be defaulted
};
struct Derive : Base
{
public:using Base::Base;
};
int main()
{Derive d(10); //Error: Calling a protected constructor of class 'Base'
}
struct Base
{
protected:Base() = default; //OK,编译器为Base合成了一个缺省构造函数,权限为public,供外界使用
};
struct Derive : Base
{
};
int main()
{Derive d; //OK
}

● 继承与友元:友元关系无法继承,但基类的友元可以访问派生类中基类的相关成员

//基类的友元
struct Base
{friend void fun(const Base&); //fun是Base的友元
public:int x;
private:int y;
protected:int z;
};
struct Derive : Base
{
private:int xxx;
};
void fun(const Base& b)
{b.x; //OKb.y; //OKb.z; //OKconst auto& d = static_cast<const Derive&>(b);d.xxx; //fun是Base的友元,Derive派生自Base,但fun并不是Derive的友元
}
//派生类的友元
struct Base
{
public:int x;
private:int y;
protected:int z;
};
struct Derive : Base
{friend void fun(const Derive&); //fun是Derive的友元
private:int xxx;
};
void fun(const Derive& d)
{d.x; //fun是Derive的友元,可以访问Derive中所有可见的基类成员d.y; //不可访问,Error: 'y' is a private member of 'Base',d.z; //fun是Derive的友元,可以访问Derive中所有可见的基类成员d.xxx; //fun是Derive的友元,可以访问Derive的所有成员
}

参考
深蓝学院: C++基础与深度解析
C++ Public, Protected and Private Inheritance

相关文章:

C++类基础(十七)

类的继承——补充知识 ● public 与 private 继承&#xff08;C Public, Protected and Private Inheritance&#xff09; 改变了类所继承的成员的访问权限 //公有继承 struct Base { public:int x; private:int y; protected:int z; }; struct Derive : public Base //公有继承…...

LeetCode刷题复盘笔记—一文搞懂贪心算法之56. 合并区间(贪心算法系列第十四篇)

今日主要总结一下可以使用贪心算法解决的一道题目&#xff0c;56. 合并区间 题目&#xff1a;56. 合并区间 Leetcode题目地址 题目描述&#xff1a; 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间…...

Andriod入门级开发

这学期有个课设&#xff0c;我们组我负责一个手机APP的开发&#xff0c;虽然刚开始说要实现什么智能导航&#xff0c;类似高德地图那种&#xff0c;但最后阉割的只剩一个Socket通信了&#xff0c;因为之前没有接触过&#xff08;可能之后也不会再接触&#xff09;&#xff0c;记…...

DCL 数据控制语言

1、简介 DCL英文全称是Data Control Language(数据控制语言)&#xff0c;用来管理数据库用户、控制数据库的访问权限。 2、管理用户 2.1 查询用户 select * from mysql.user;查询的结果如下: 其中 Host代表当前用户访问的主机, 如果为localhost, 仅代表只能够在当前本机访问…...

全网超详细的下载与安装VMware虚拟机以及为什么要安装VMware虚拟机

文章目录1. 文章引言2. 下载VMware3. 安装VMware1. 文章引言 我们使用最多的系统是windows系统&#xff0c;因为&#xff0c;国内电脑厂商的操作系统(os)基本是windows系统&#xff0c;比如华为、联想、华硕等电脑。 但线上的服务器大多是Linux系统&#xff0c;而我们经常使用…...

Python获取zabbix问题触发器

背景&#xff1a;阿里云的ECS服务器因为阿里云升级插件&#xff0c;导致安全防护程序重启&#xff0c;产生不同的端口。导致低自动发现注册的端口 大量报警。 解决&#xff1a;杀掉关于因为非业务 变更的端口检测的触发器。 相关文档&#xff1a; Zabbix监控之主机端口监控自…...

原型链污染

目录 前置知识 原型对象 prototype和__proto__的区别 原型链概念 原型链的继承 原型 链污染 原型链污染原理 javascript中可能会存在原型链污染的危险函数 原型链污染的实际应用 JavaScript中可以触发弹窗的函数 前置知识 原型对象 在JavaScript中&#xff0c;每个函…...

ClickHouse详解

一、概念ClickHouse是一个用于联机分析(OLAP)的列式数据库管理系统(DBMS)。OLAP场景的关键特征绝大多数是读请求数据以相当大的批次(> 1000行)更新&#xff0c;而不是单行更新;或者根本没有更新。已添加到数据库的数据不能修改。对于读取&#xff0c;从数据库中提取相当多的…...

02_Docker 安装

02_Docker 安装 文章目录02_Docker 安装2.1 安装 Docker 的先决条件2.2 在 Ubuntu 和 Debain 中安装 Docker2.2.1 检查前提条件1. 内核2.检查 Device Manager2.2 安装 DockerDocker 支持非常多的Linux平台&#xff0c;包括Ubuntu和RHEL&#xff0c;除此之外&#xff0c;Docker还…...

K8S集群将Docker切换到Containerd

文章目录1. 开启节点维护1.1 将节点设置成不可调度1.2 驱逐节点上的 Pod1.3 停止相关服务2. 升级到 containerd2.1 安装 containerd2.2 调整 containerd 配置2.3 修改 kubelet 启动配置参数3. 重启节点服务4. 验证升级后的节点5. 容器管理工具5.1 容器管理命令行工具对比5.2 cr…...

Kubernetes03:kubernetes 功能和架构

2.1 概述 Kubernetes 是一个轻便的和可扩展的开源平台&#xff0c;用于管理容器化应用和服务。通过 Kubernetes 能够进行应用的自动化部署和扩缩容。在 Kubernetes 中&#xff0c;会将组成应用的容 器组合成一个逻辑单元以更易管理和发现。Kubernetes 积累了作为 Google 生产环…...

LabVIEW中CPU和内存使用情况在NI分布式系统管理器中不可见

LabVIEW中CPU和内存使用情况在NI分布式系统管理器中不可见想使用NI分布式系统管理器监测网络连接实时控制器的CPU和内存使用情况。从左侧窗口的树中选择了感兴趣的实时目标&#xff0c;然后通过选择视图自动视图来确保启用自动查看。希望看到CPU/内存选项卡&#xff0c;但它有显…...

buu [NPUCTF2020]Classical Cipher 1

题目描述&#xff1a; 题目分析&#xff1a; 首先输入密码 {gsv_pvb_rh_zgyzhs} 后&#xff0c;得到&#xff1a;可以得知密码是错误的&#xff0c;再看看密码 {gsv_pvb_rh_zgyzhs} &#xff0c;排列无序&#xff0c;那么尝试用凯撒与栅栏解密&#xff0c;发现还是解不出&…...

分享96个HTML体育竞技模板,总有一款适合您

分享96个HTML体育竞技模板&#xff0c;总有一款适合您 96个HTML体育竞技模板下载链接&#xff1a;https://pan.baidu.com/s/1k2vJUlbd2Boduuqqa0EWMA?pwdj8ji 提取码&#xff1a;j8ji Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 北京奥运火炬PSD模板 奥运…...

Python pandas「原有或者新建」Excel中「追加新或者新建」sheet

1.pandas原有Excel中追加新sheet 使用Pandas库&#xff0c;我们可以轻松将数据追加到现有的Excel工作簿中的新工作表中。以下是追加新工作表的简单步骤&#xff1a; 读取现有的Excel文件 使用Pandas库中的read_excel()函数读取现有的Excel文件。指定Excel文件的路径和文件名&a…...

程序员必备的软技能- CPU“没有灵魂的躯体”

引言 先引用一段比较有意思的论述&#xff1a; 现实中每个人是由两部分构成&#xff0c;灵魂和躯体&#xff0c;灵魂依附于躯体游走于世间&#xff0c;现实中我们面对的每个人其实面对的是其灵魂而非肉体&#xff0c;肉体不过是表象而已。 灵魂本性乃一恶物&#xff0c;寄生于…...

基于微信小程序的青少年生理健康知识小助手

基于微信小程序的青少年生理健康知识小助手 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目…...

【scl】博图程序的导入和导出

导入或者导出博图文件的方法&#xff08;也叫移植文件&#xff09; 目录 前言 ​编辑 ​编辑 前言 本篇文章主要写一下关于博图文件的导入和导出&#xff0c;具体要怎么样才能将写好的程序或者块移植到其他地方&#xff0c;下面我们一起来看&#xff01; 一、程序块的导入和导…...

【C语言】指针进阶

目录 一、字符指针 二、指针数组 三、数组指针 四、数组指针的使用 五、函数指针数组 六、指向函数指针数组的指针 七、回调函数 我们知道了指针的概念&#xff1a; 1. 指针就是个变量&#xff0c;用来存放地址&#xff0c;地址唯一标识一块内存空间。 2. 指针的大小是…...

18:CTK 总结篇(FAQ)

作者: 一去、二三里 个人微信号: iwaleon 微信公众号: 高效程序员 经过了几个月的艰苦奋战,终于到了最后一节啦,是不是和我一样,心里有点儿小激动! 回顾之前的章节,从初级 -> 进阶 -> 高级,我们针对 CTK 做了详细的分类讲解。希望通过这些知识,大家能对模块化…...

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

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

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

力扣-35.搜索插入位置

题目描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

day36-多路IO复用

一、基本概念 &#xff08;服务器多客户端模型&#xff09; 定义&#xff1a;单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用&#xff1a;应用程序通常需要处理来自多条事件流中的事件&#xff0c;比如我现在用的电脑&#xff0c;需要同时处理键盘鼠标…...

解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist

现象&#xff1a; android studio报错&#xff1a; [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决&#xff1a; 不要动CMakeLists.…...