当前位置: 首页 > 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 做了详细的分类讲解。希望通过这些知识,大家能对模块化…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题

在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件&#xff0c;这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下&#xff0c;实现高效测试与快速迭代&#xff1f;这一命题正考验着…...