C++继承特性(4)——友元与静态

news2024/9/21 16:40:54

目录

一.继承与友元的关系

二.继承与静态成员的关系 

先回顾一下静态成员变量:

运行TestPerson()函数:

测试案例2:

三.练习题:


一.继承与友元的关系

友元关系不能被继承,也就是说父类中的友元函数不能访问子类私有和保护成员

class Student;
class Person{
public:
	//友元声明
	friend void Display(const Person& p, const Student& s);
protected:
	string _name; // 姓名
};

class Student : public Person{
public:
    //...
protected:
	int _stuNum; // 学号
};

void Display(const Person& p, const Student& s){
	cout << p._name << endl;
	//cout << s._stuNum << endl;	//报错,除非让子类中也使用友元声明
}

int main(){
	Person p;
	Student s;
	Display(p, s);
	return 0;
}

 

 

        如上图:友元函数Display只在父类中声明过,所以友元函数可以访问父类的成员变量,Student虽然为Person的子类,但是友元是不会被继承下来的,也就是说父辈那一代是朋友关系,但并不意味着父辈的子女与其也是朋友关系。 

        想让子类也能使用父类的友元函数,需要在子类中也加入友元声明!

二.继承与静态成员的关系 

先回顾一下静态成员变量:

1.它并不在类对象中存放,它在静态区。
2.而且静态成员变量的创建在类内,定义是在该类的外面定义,定义时需要进行初始化赋值!!!

3.一个类对象被创建时,类对象中只有类的成员变量(静态成员变量除外)!!!
4.成员函数不在类对象中!!!
5.类对象的大小是根据类的成员变量规定的大小!

总之,静态成员变量是被所有类对象所共享的,它只有一份。

class Person{
public:
	Person() { ++_count; }
	void Print() {
		//_name = "zzz";
		cout << "Print()函数" << endl;
	    }
public:
	string _name; // 姓名
	int _age;
	static int _count; // 统计人的个数。
};
//父类的静态成员变量
int Person::_count = 0;

//子类
class Student : public Person{
protected:
	int _stuNum; // 学号
};

//孙子类
class Graduate : public Student{
protected:
	string _seminarCourse; // 研究科目
};

void TestPerson(){
	Student s1;
	Student s2;
	Student s3;
	Graduate s4;
	cout << " 人数 :" << Person::_count << endl;
	Student::_count = 0;
	cout << " 人数 :" << Person::_count << endl;
}

        在父类Person的构造函数中,每调用一次构造函数,静态成员变量_count的值就会加1。

        现如今有一个继承父类的子类和一个继承子类的孙子类。        

        测试函数中,创建了四个对象,该静态成员变量的值为多少? 

运行TestPerson()函数:

 

        通过结果的运行可知,_count的值为4, 原因:前三个对象的创建自然不必说,都是调用自家类的构造函数,而对于孙子类Graduate的对象创建,它虽然是继承自子类Student,但是Student也是继承于Person类,它们之间有血缘关系,那么孙子类的对象创建自然也离不开父类的构造函数!!!

测试案例2:

运行结果:

         通过结果可知:父类对象与子类对象的_count是同一份,无论是值还是地址都完全相同,所以推断结论:父类的静态成员变量会被子类所继承,子类使用的_count与父类的是同一个_count

而且只要一方将静态成员值修改了,那么只要与该静态成员有关的类所对应的值也都会变。 

 

三.练习题:

class Person{
public:
	Person() { ++_count; }
	void Print() {
		cout << "Print()函数" << endl;
	    }
public:
	string _name; // 姓名
	int _age;
	static int _count; // 统计人的个数。
};
//父类的静态成员变量
int Person::_count = 0;


void Test3() {
	Person *ptr=nullptr;

	//代码1:					
	cout << ptr->_name << endl;
	//代码2:
	cout << ptr->_age << endl;
	//代码3:
	cout << ptr->_count << endl;
	//代码4:
	ptr->Print();
}

int main(){
    Test3();
}

 在Test3()函数中,执行以下每一条代码时,结果是什么

    //代码1:                     cout << ptr->_name << endl;
    //代码2:                     cout << ptr->_age << endl;
    //代码3:                     cout << ptr->_count << endl;
    //代码4:                     ptr->Print();

考题解析:


       代码1的结果会出现异常,因为Person类创建的对象是指针类型的,一开始指针对象被初始化为空,该指针对象ptr中的成员变量_name值也是空的,所以当ptr访问它的成员变量_name时会出错(空指针访问成员变量会异常);

        代码2的结果也是异常,与代码1性质相同,都是空指针访问了其成员变量。
    
       代码3结果正确,因为静态成员变量并不在父类对象ptr中!!!,它是在静态区存放。
       代码4结果正确,因为成员函数Print也不在父类对象ptr中!!!,况且在成员函数中,并没有访问其成员变量(并没有发生空指针访问成员变量的行为),所以该对象访问成员函数行为无异常。

        强调:类对象中只存储非静态成员变量,所以类对象的大小由类所拥有的成员变量所决定。并且类对象不存储成员函数,也不存储静态成员变量。

 

 

 

若是父类的Print函数中,访问了成员变量:

那么:

   Person *ptr=nullptr;
    //代码4:
    ptr->Print();

        代码4的运行就如同上面的代码1的结果一样,运行异常报错,ptr为空,虽然访问了成员函数这一步没有报错,但进入到成员函数体运行其语句时,发现执行了_name=“zzz”;语句,该语句相当于this->_name访问成员变量,类对象访问成员函数就是将该对象的地址传给类的this指针,此时this指针相当于是空指针,空指针访问成员变量,报错!!!

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

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

相关文章

IT职场笔记

MySQL笔记之一致性视图与MVCC实现 一致性读视图是InnoDB在实现MVCC用到的虚拟结构&#xff0c;用于读提交&#xff08;RC&#xff09;和可重复度&#xff08;RR&#xff09;隔离级别的实现。 一致性视图没有物理结构&#xff0c;主要是在事务执行期间用来定义该事物可以看到什…

Python爬虫+数据可视化:分析唯品会泳衣数据详情

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 唯品会是中国领先的在线特卖会电商平台之一&#xff0c;它以“品牌特卖会”的模式运营&#xff0c;为会员提供品牌折扣商品。 唯品会的商品包括服装、鞋类、箱包、美妆、家居、母婴、食品等各类品牌产品。 这就是今天…

RFID在半导体行业的应用解决方案

半导体行业近几年来受到疫情因素和政治因素的影响&#xff0c;导致国内芯片的短缺问题十分严重&#xff0c;在国家大力发展制造企业的趋势下&#xff0c;不少企业也加大了芯片制造工厂的投入。RFID作为一种可非接触识别的技术&#xff0c;是如何应用在半导体行业中的?下面我们…

JsonPath使用和示例

JsonPath使用和示例 1 简介2 官方实例3 JsonPath与XPath语法对比4 实例说明JsonPath与XPath语法5 Python中JsonPath模块6 Python中JsonPath使用7 结合接口测试的实例 1 简介 官网&#xff1a;https://goessner.net/articles/JsonPath/&#xff1b;JsonPath 是一种简单的方法来…

做了5年软件测试决定离职,跳槽历经40场面试, 面的基本都是大厂

前言 沉寂了好一段日子&#xff0c;连我们公司自己人都问我为什么最近都不写文章了。 那么当看到本篇的标题的时候&#xff0c;大家应该可以猜到这是为什么了。 我最终还是决定要离开服务了 5 年多的公司。 而这次跳槽历经 3 个月&#xff0c;前后聊了 10 家公司&#xff0c;进…

问题:idea启动项目错误提示【command line is too long. shorten command line】

问题&#xff1a;idea启动项目错误提示【command line is too long. shorten command line】 参考博客 问题描述 启动参数过长&#xff0c;启动项目&#xff0c;错误提示 原因分析 出现此问题的直接原因是&#xff1a;IDEA集成开发环境运行你的“源码”的时候&#xff08…

Spring学习笔记之入门程序

文章目录 关于下载介绍jar包第一个入门程序关于入门程序的小细节启用Log4j2 关于下载 这是一个悲惨而又戏剧性的故事 其实是不用下的&#xff0c;spring的jar包是归meaven管的&#xff0c;不用特地的去spring官网再去什么github上下载&#xff0c;再去看什么乱七八糟的目录&a…

IDEA的基础使用——【初识IDEA】

IDEA的基础使用——【初识IDEA】 文章目录 IDEA简介前言官网 IDEA的下载与安装选择下载路径勾选自己需要的其余按默认选项进行即可 目录简介安装目录简介 运行Hello WorldIDEA快捷键常用模板模板一&#xff1a;psvm&#xff08;main&#xff09;模板二&#xff1a;模板三&#…

adb常用命令使用

1.查看当前运行的包名和Activity adb shell dumpsys window | findstr mCurrentFocus 2.卸载app adb uninstall io.appium.settings adb uninstall io.appium.unlock adb uninstall io.appium.android.ime

Ubutun安装中文语言和搜狗输入法

Unbuntu版本是18.04的。要安装中文语言和搜狗输入法。 参考官方说明 Install languages 安装网址&#xff1a;搜狗输入linux安装网址 安装搜狗输入法&#xff1a;看搜狗输入法的指南是最权威的&#xff1a; 搜狗输入法安装指南linux 拖拽语言&#xff08;最开始中文是在下面的…

软件外包开发的后台开发语言

在软件外包开发中&#xff0c;后台语言的选择通常取决于项目需求、客户偏好、团队技能和开发效率。今天和大家分享一些常用的后台语言及选择它们的原因&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。…

软件测试质量度量之 “三级指标体系”

管理学大师彼得 - 德鲁克曾说过&#xff1a;无数据不管理。 数字是人们快速认知事物的一种有效方式。无论在生活还是工作&#xff0c;对事还是对人都息息相关。碰上难以的用数字描述事物或现象肯定是没有找对适用的指标和度量方式。尤其对于质量工程方面的工作&#xff0c;定量…

从小白到大神之路之学习运维第70天-------Docker容器引擎基础

第四阶段提升 时 间&#xff1a;2023年7月31日 参加人&#xff1a;全班人员 内 容&#xff1a; Docker容器引擎基础 目录 一、Docker概述 &#xff08;一&#xff09;容器背景&#xff1a; &#xff08;二&#xff09;云计算模式&#xff1a; &#xff08;三&#x…

Python+OpenCV实现自动扫雷,挑战扫雷世界记录!

目录 准备 - 扫雷软件 实现思路 - 01 窗体截取 - 02 雷块分割 - 03 雷块识别 - 04 扫雷算法实现 福利&#xff1a;文末有Python全套资料哦 我们一起来玩扫雷吧。用PythonOpenCV实现了自动扫雷&#xff0c;突破世界记录&#xff0c;我们先来看一下效果吧。 中级 - 0.74秒 …

大数据技术之Clickhouse---入门篇---安装

星光下的赶路人star的个人主页 努力到无能为力&#xff0c;拼搏到感动自己 文章目录 1、ClickHouse的安装1.1 准备工作1.1.1 确定防火墙处于关闭状态1.1.2 CentOS取消打开文件数限制1.1.3 安装依赖&#xff08;所有节点都进行依赖安装&#xff09;1.1.4 CentOS取消SELINUX 1.2 …

OPC DA 客户端与服务器的那点事

C#开发OPC客户端&#xff0c;使用OPCDAAuto.dll。在开发过程中偶遇小坎坷&#xff0c;主要记录一下问题解决办法。 1、建立客户端&#xff0c;参考链接。建立WinFrom工程&#xff0c;将博客中代码全部复制即可运行&#xff1a; https://www.cnblogs.com/kjgagaga/p/17011730.…

Linux 查看服务器内存、CPU、网络等占用情况的命令

1、查看物理CPU个数&#xff1a;cat cat /proc/cpuinfo | grep "physical id" | sort | uniq | wc -l 2、查看服务器CPU内核个数&#xff1a;cat 每个物理CPU中core的个数&#xff08;即核数&#xff09; cat /proc/cpuinfo | grep "cpu cores" | u…

【数据库】事务隔离级别

事务特征ACID 原子性&#xff08;Atomicity&#xff09;&#xff1a;事务中的所有操作要么全部执行成功&#xff0c;要么全部失败回滚&#xff0c;没有中间状态。它确保了数据的完整性。一致性&#xff08;Consistency&#xff09;&#xff1a;事务执行后&#xff0c;数据库从…

02_modbus从站从开始初始化到接收一帧数据的流程

0. 协议栈接收状态的变化图 1.协议栈的初始化和使能 void eMBRTUStart( void ) {ENTER_CRITICAL_SECTION( );/* Initially the receiver is in the state STATE_RX_INIT. we start* the timer and if no character is received within t3.5 we change* to STATE_RX_IDLE. This…

网络请求fetch

fetch()是 XMLHttpRequest 的升级版&#xff0c;用于在 JavaScript 脚本里面发出 HTTP 请求。浏览器原生提供这个对象 fetch()的功能与 XMLHttpRequest 基本相同&#xff0c;但有三个主要的差异。 与 Ajax 类似&#xff0c;Fetch 也是前后端通信的一种方式。Fetch 要比 Ajax …