C++15 ---继承2:重载与覆盖、隐藏、拷贝构造函数、赋值运算符重载、静态数据成员

news2025/1/13 13:54:39

一、重载与覆盖的特征

1、重载

成员函数被重载的特征:
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4) virtual关键字可有可无。

2、覆盖

覆盖是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual关键字。

二、隐藏

派生类的成员函数和基类的函数同名同参,则将基类的函数隐藏。

这里“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:

(1)如果派生类的函数与基类的函数同名,但是参数不同
此时,不论有无 virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。
此时,基类的函数被隐藏(注意别与覆盖混淆)。

示例代码1:

class A
{
public:
	void print() { cout << "A::print" << endl; }
};
/*
隐藏:派生类的成员函数和基类的函数同名同参,则将基类的函数隐藏
*/
class B :public A
{
public:
	//print将派生下来的A的print隐藏了
	void print() 
	{
		cout << "B::print" << endl; 
	}
};
void main()
{
	A a;
	B b;
	a.print();
	b.print();

}

运行结果:

在这里插入图片描述

示例代码2:

class A
{
public:
	void print() { cout << "A::print" << endl; }
protected:
	int m_i;
};
/*
隐藏:派生类的成员函数和基类的函数同名同参,则将基类的函数隐藏
*/
class B :public A
{
public:
	//print将派生下来的A的print隐藏了
	void print() 
	{
		cout << "B::print" << endl; 
		cout << m_i << " " << A::m_i << endl;
	}
	void set() { m_i = 10; A::m_i = 20; }
protected:
	int m_i;
};
void main()
{
	A a;
	B b;
	a.print();
	b.set();
	b.A::print();
	b.print();
	cout << sizeof(B) << endl;
}

运行结果:

在这里插入图片描述

三、继承的有参无参构造函数注意点-有无参构造,并且有指针数据成员。

对于以下代码,无法正常实现

class Person
{
public:
	Person(){cout << "Person()" <<endl;}
	Person(const char *name,char sex,int age):m_sex(sex),m_age(age)
	{
		m_name = new char[strlen(name) + 1];
		strcpy_s(m_name,strlen(name) +1,name);
	}
	void print()
	{
		cout << m_name <<" "<< m_sex <<" "<< m_age <<" ";
	}
private:
	char *m_name;
	char m_sex;
	int m_age;
};

class Student:public Person
{
public:
	Student(){cout << "Student()" <<endl;}
	Student(int num,const char *name,char sex,int age,int score):Person(name,sex,age),m_num(num),m_score(score){}
	void print()
	{
		cout << m_num << " ";
		Person::print();
		cout << m_score << endl;
	}
private:
	int m_num;
	int m_score;
};

void main()
{
	Student s;
	Student s1(1001,"yasuo",'f',21);

	s.print();//error,出错点
	s1.print();
	
}

在这里插入图片描述

理解:

Person类和Student类的内存布局:
在这里插入图片描述
而主程序定义了无参对象s和有参对象s1.
而无参对象s,构造时,没能为其中的指针char *m_name;开辟空间,
就例如下述代码:

void main()
{
	int *p;
	cout << p << endl;//erroe,其没有指向合法的内存空间
}

解决方法:

有无参构造,并且有指针数据成员。需要在无参构造函数里为其开辟空间,一个空间作为占位符。

class Person
{
public:
	//Person():m_sex('f'),m_age(20)
	Person()
	{
		m_name = new char[1];
		*m_name = '\0';
	}
	Person(const char *name,char sex,int age):m_sex(sex),m_age(age)
	{
		m_name = new char[strlen(name) + 1];
		strcpy_s(m_name,strlen(name) +1,name);
	}
	~Person()
	{
		if(m_name != NULL)
		{
			delete[]m_name;
			m_name = NULL;
		}
	}
private:
	char *m_name;
	char m_sex;
	int m_age;
};

在这里插入图片描述

四、继承的拷贝构造函数、赋值运算符重载使用:

示例代码:

class Person
{
public:
	Person():m_sex('f'),m_age(20)
	{ 
		m_name = new char[1];
		*m_name = '\0';
		cout << "Person()" << endl; 
	}
	Person(const char* name, char sex, int age):m_sex(sex),m_age(age)
	{
		m_name = new char[strlen(name) + 1];
		strcpy_s(m_name, strlen(name) + 1, name);
	}
	Person(Person& p) :m_sex(p.m_sex), m_age(p.m_age)//拷贝构造函数
	{
		m_name = new char[strlen(p.m_name) + 1];
		strcpy_s(m_name, strlen(p.m_name) + 1, p.m_name);
	}
	Person& operator=(Person& p)//赋值运算符重载
	{
		if (this == &p)
			return *this;
		delete[]m_name;
		m_name = new char[strlen(p.m_name) + 1];
		strcpy_s(m_name, strlen(p.m_name) + 1, p.m_name);
		
		m_sex = p.m_sex;
		m_age = p.m_age;
		return *this;
	}
	void print()
	{
		cout << m_name << " " << m_sex << " " << m_age << " ";
	}
	~Person()
	{
		if (m_name != NULL)
		{
			delete[]m_name;
			m_name = NULL;
		}
	}
private:
	char* m_name;
	char m_sex;
	int m_age;
};
class Student :public Person
{
public:
	Student():m_num(0),m_score(0) { cout << "Student()" << endl; }
	Student(int num, const char* name, char sex, int age, int score):m_num(num),Person(name,sex,age),m_score(score) {}
	void print()
	{
		cout << m_num << " ";
		Person::print();
		cout << m_score << endl;
	}
	Student(Student& s) :Person(s), m_num(s.m_num), m_score(s.m_score) {}//拷贝构造函数
	Student& operator=(Student& s)//赋值运算符重载
	{
		if (this == &s)
			return *this;
		Person::operator=(s);
		m_num = s.m_num;
		m_score = s.m_score;
		return *this;
	}
private:
	int m_num;
	int m_score;
};

void main()
{
	Student s;
	Student s1(1001, "zhangsan", 'f', 20, 78);
	s.print();
	s1.print();
	Student s2(s1);//调用拷贝构造函数
	s2.print();
	s = s1;//调用赋值运算符重载
	s.print();
}

运行结果:

在这里插入图片描述

五、继承情况下静态数据成员的使用

基类继承后,子类也有对静态数据成员的使用权,是共享的。
但不占类内空间。

示例代码:

class Person
{
public:
	Person(int num = 1000) :m_num(num) {}
	void print()
	{
		cout << "count = " << m_count << endl;
	}
protected:
	int m_num;
	static int m_count;//静态数据成员
};

int Person::m_count;//外部二次声明,对该静态成员进行初始化

//三个继承类:
class Student :public Person
{
public:
	Student(int num, const char* job) :Person(num)
	{
		m_job = new char[strlen(job) + 1];
		strcpy_s(m_job, strlen(job) + 1, job);
		m_count++;
	}
private:
	char* m_job;
};
class Teacher :public Person
{
public:
	Teacher(int num,const char*job):Person(num) 
	{
		m_job = new char[strlen(job) + 1];
		strcpy_s(m_job, strlen(job) + 1, job);
		m_count++;
	}
private:
	char* m_job;
};
class Worker :public Person
{
public:
	Worker(int num,const char*job) :Person(num)
	{
		m_job = new char[strlen(job) + 1];
		strcpy_s(m_job, strlen(job) + 1, job);
		m_count++;
	}
private:
	char* m_job;
};
void main()
{
	Student s(1001, "student");
	Teacher t(1002, "teacher");
	Worker w(1003, "worker");
	w.print();
	t.print();
	s.print();
	Worker w1(1006, "worker");
	s.print();
	cout << sizeof(Worker) << endl;//为8字节,静态数据成员不占类的内存单元
}

运行结果:

在这里插入图片描述

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

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

相关文章

STM32CubeMX环境安装(保姆级)

目录 JAVA环境安装 安装包 文件夹设置 运行exe STM32CubeMX下载 第一步 第二步 第三步 第四步 第五步 第六步 第七步 第八步 注意&#xff0c;我们使用STM32CubeMX需要安装JAVA环境&#xff01;&#xff01;&#xff01; JAVA环境安装 安装包 JAVA下载链接&…

《FFmpeg Basics》中文版-02-显示帮助和功能

正文 关于FFmpeg程序的帮助和其他信息都显示在空格和连字符之后输入的各种选项&#xff0c;示例显示了FFmpeg工具的用法&#xff0c;但是相同的选项对于ffplay、ffprobe和ffserver是有效的。参数是区分大小写的。FFmpeg组件的开发速度很快&#xff0c;从2012年11月开始&#x…

MicroPython——有点东西,但是不多

引言 之前做过一个树莓派驱动墨水屏的项目&#xff0c;本来想整理出来与大家分享的&#xff0c;但是由于树莓派已经成了理财产品&#xff0c;所以为了让这个项目更加具有实践意义&#xff0c;最近我打算把这个项目移植到ESP32上。在树莓派上我使用的是Python编写的代码&#x…

C++简单工厂模式详解

C简单工厂模式详解1.问题引入2.编写代码思路的迭代2.1 main函数主体内编写全部代码2.2 修改上述问题后的main函数代码2.3 引入面向对象后的代码2.4 加上继承和多态后的代码3.C简单工厂代码4.总结4.1 简单工厂模式适用场景4.2收获1.问题引入 编写一个计算器程序代码&#xff0c…

论文笔记:Region Representation Learning via Mobility Flow

2017 CIKM 1 摘要和介绍 使用出租车出行数据学习区域向量表征 同时考虑时间动态和多跳位置转换——>通过flow graph和spatial graph学习表征出租车交通流可以作为区域相似度的一种 A区域和B区域之间流量大 ——>A和B的特征更相关——>用一个/很相似的vector来表征他…

如何实现基于场景的接口自动化测试用例?来看看大佬的方案

自动化本身是为了提高工作效率&#xff0c;不论选择何种框架&#xff0c;何种开发语言&#xff0c;我们最终想实现的效果&#xff0c;就是让大家用最少的代码&#xff0c;最小的投入&#xff0c;完成自动化测试的工作。 基于这个想法&#xff0c;我们的接口自动化测试思路如下…

R语言七天入门教程七:项目实战

R语言七天入门教程七&#xff1a;项目实战 在完成之前R语言基础知识的学习后&#xff0c;今天的内容是项目实战&#xff0c;通过完成一些小项目来巩固知识。 一、矩阵运算计算器&#xff08;变量与运算符练习&#xff09; 1、问题描述 给定矩阵A和B&#xff0c;计算矩阵相加…

MySql常用内置函数详解

目录日期函数--了解***字符串函数--重要数学函数--了解其他函数--了解MySql为我们提供了一些内主函数&#xff0c;方便我们对特定数据进行相关操作&#xff01; 注意:都是配合select使用哦&#xff0c;个人理解SQL的select相当于C中的printf; 日期函数–了解 一般用于insert in…

C++ 主函数几种语法

Cmain函数的两种写法 1&#xff0c;返回值为int&#xff0c;且main不带参数 #include<iostream> using namespace std; int main() { cout << "Hello C \n" << endl; system("pause"); return 1;//函数返回值取值范围0到255&#xf…

深入了解 JavaScript 语法错误以及如何防止它们

最近&#xff0c;在 Leader 的建议下&#xff0c;去看了看 emotion 和 storybook 的相关文档。学习过后&#xff0c;小有收获。因此&#xff0c;这次将以我自己的视角带你们体验一下 storybook&#xff0c;也算是对我自己学习过程中的一个 review。 何为 storybook 什么是 st…

第2关:伪分布式体验及分布式安装配置

服务器leader选举 为进一步了解ZooKeeper的leader选举过程&#xff0c;本节实训利用服务器的关闭启动&#xff0c;观察服务器的leader产生过程。利用以下命令查看当前服务器节点的状态(/xxx为安装目录)&#xff1a; ./xxx/bin/zkServer.sh status 当仅启动1个服务器节点&…

进博会期间,多地政府领导密集考察深兰科技

从11月初开始&#xff0c;借第五届中国国际进口博览会在上海举办的契机&#xff0c;来自全国各地的地级、县级市的各级领导纷纷来到上海&#xff0c;深入到各个行业领域的国企、央企、民企和跨国企业中走访调研&#xff0c;寻求技术合作&#xff0c;洽谈招商引资。 期间仅1日至…

流体力学基础——简介

流体定义&#xff1a;无规则的运动&#xff0c;流体&#xff1b;流体在静止时内部不能产生剪切力&#xff0c;流动产生的剪切力叫做粘力流体特点&#xff1a; 1、力与变形的关系不同&#xff1b;固体&#xff0c;应力正比于应变&#xff0c;静力学为主&#xff1b;流体&#xf…

DeepLearn关于数组和数的操作

本篇文章纯属作为自己的笔记&#xff0c;因为每次写程序都忘记下面的内容&#xff0c;找起来又很浪费时间&#xff0c;所有就索性一次性都整理下来&#xff0c;后续又不新的不会的内弄也会及时更新到文章当中&#xff0c;方便以后查阅。 DeepLearn关于数组和数的操作Python标准…

【详解】BIO、AIO、NIO Netty 知识点和工作原理

Netty框架 基础 三大网络编程 BIO 同步阻塞:服务器实现模式一个连接一个线程,既客户端有连接请求时,服务器就需要启动一个线程进行处理,如果这个连接不任何事情会造成不必要的线程线程开销 适用场景&#xff1a; 连接数目比较小且固定的架构&#xff0c;这种方式对服务器资源…

Android企业微信分享到小程序

1.官方文档Android应用 - 接口文档 - 企业微信开发者中心https://developer.work.weixin.qq.com/document/path/91196 2.创建应用 登录企业微信管理后台&#xff0c;选择企业应用&#xff0c;选择“企业微信授权登录”&#xff0c;在设置界面填写Android的 App的签名&包名…

[附源码]java毕业设计基于技术的新电商助农平台

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

HTTP 消息头

title: HTTP 消息头 date: 2022-11-16 14:36 tags: [HTTP,X-Real-IP,Host,X-Forwarded-For,Nginx] 文章目录〇、问题一、前言二、什么是消息头&#xff1f;三、Host四、X-Real-IP五、X-Forwarded-For参考更新〇、问题 什么是HTTP Headers&#xff1f;作用是什么&#xff1f; …

qemu-system-aarch64使用记录

qemu-system-aarch64 使用记录下载安装qemu查看是否支持KVM运行qemu-M内核启动问题内核编译下载安装qemu #!/bin/bashsudo apt update > /dev/null sudo apt upgrade > /dev/null sudo apt-get install -y make gcc g git > /dev/nullcd sudo apt-get install -y r…

一起来庆祝属于GISer的节日GIS DAY

概述 作为一名GISer的你&#xff0c;有没有想过其实我们GISer也有自己的节日&#xff1f;这个节日便是GIS DAY&#xff0c;今年的GIS DAY恰在今天&#xff08;2022年11月16日&#xff09;。究竟什么是GIS DAY&#xff1f;这里为大家介绍一下这个节日。 什么是GIS DAY GIS DA…