记录C++中,子类同名属性并不能完全覆盖父类属性的问题

问题代码:

        首先看一段代码:很简单,就是BBB继承自AAA,然后BBB重写定义了同名属性,然后调用父类AAA的打印函数:

#include <iostream>
using namespace std;

class AAA {
public:
	AAA() {}
	~AAA() {}
	
	void func() {
		YourVar = 20;
	}
	
	void print() {
		cout << "YourVar: " << YourVar << endl;
	}
	
public:
	int YourVar = 10;
	
};

class BBB : public AAA {
public:
	BBB() {
		YourVar = 20;
	}
	~BBB() {}
	
	void print1() {
		cout << "YourVar: " << YourVar << endl;
	}
	
	void YourMethodOrFunction() {}
	
private:
	int YourVar;
};

int main() {
	BBB b;
	b.print();
	//b.print1();
	
	cout << "********" << endl;
	
	return 0;
}

打印结果:

        会发现,明明我构造函数里面将YourVar的值改为了20,但是还是打印的10.

        这个问题,属于C++的基础问题,我记得,子类继承父类,如果子类中,定义了同名属性的话,那么父类的属性会被隐藏,访问子类的那个属性,就是子类的,不会是父类的。

        但是如果父类里面,有一个打印的函数print,会发现,这个print函数,生效的范围,只有父类,不包括子类。只有将父类的print函数重写,才能生效在子类中:

解决思路1:重写print

#include <iostream>
using namespace std;

class AAA {
public:
	AAA() {}
	~AAA() {}
	
	void func() {
		YourVar = 20;
	}
	
	void print() {
		cout << "YourVar: " << YourVar << endl;
	}
	
public:
	int YourVar = 10;
	
};

class BBB : public AAA {
public:
	BBB() {
		YourVar = 20;
	}
	~BBB() {}
	
	void print() {
		cout << "YourVar: " << YourVar << endl;
	}
	
	void YourMethodOrFunction() {}
	
private:
	int YourVar;
};

int main() {
	BBB b;
	b.print();
	
	cout << "********" << endl;
	
	return 0;
}

打印结果:

虽然解决了问题,但是明明我父类中,写了print函数,干嘛还重新写一次?还有意义?

解决思路2:去掉子类的同名属性

#include <iostream>
using namespace std;

class AAA {
public:
	AAA() {}
	~AAA() {}
	
	void func() {
		YourVar = 20;
	}
	
	void print() {
		cout << "YourVar: " << YourVar << endl;
	}
	
public:
	int YourVar = 10;
	
};

class BBB : public AAA {
public:
	BBB() {
		YourVar = 20;
	}
	~BBB() {}
	
	
//private:
//	int YourVar;
};

int main() {
	BBB b;
	b.print();
	
	cout << "********" << endl;
	
	return 0;
}

但是有时候,我们就是要这么重写,那么该怎么办呢?

解决思路3:将父类地址传递给子类

#include <iostream>
using namespace std;

class AAA {
public:
	AAA() {
		YourVar = new int;
		*YourVar = 10;
	}
	~AAA() {
		delete YourVar;
	}
	
	void print() {
		cout << "YourVar: " << *YourVar << endl;
	}
	
protected:
	int *YourVar;
};

class BBB : public AAA {
public:
	BBB() {

		// 将父类地址传递给子类
		YourVar = AAA::YourVar;
		*YourVar = 20;
	}
	~BBB() {}
	
private:
	int *YourVar;
};

int main() {
	
	BBB b;
	b.print();
	
	cout << "********" << endl;
	
	return 0;
}

解决思路4:将子类地址传递给父类:

#include <iostream>
using namespace std;

class AAA {
public:
	AAA() {
		// YourVar = new int;
		// *YourVar = 10;
	}
	~AAA() {
		delete YourVar;
	}
	
	void print() {
		cout << "YourVar: " << *YourVar << endl;
	}
	
protected:
	int *YourVar;
};

class BBB : public AAA {
public:
	BBB() {
		YourVar = new int;
		// 将子类地址传递给父类
		AAA::YourVar = YourVar;
		*YourVar = 20;
	}
	~BBB() {}
	
private:
	int *YourVar;
};

int main() {
	
	BBB b;
	b.print();
	
	cout << "********" << endl;
	
	return 0;
}

总结

1. 面对这样的情况,要么就不要写同名属性(但有时候不能保证自己忘记了)

2. 当以后继承的类层次很多的时候,难免会定义同名属性,但是父类的函数,是不会访问子类的同名属性的,这个是这个问题的关键。虽然在子类中,父类的属性确实是隐藏了,但隐藏不代表消失,也不代表父类的函数中,也将这个属性给隐藏或者替换了。

3. 要么就使用指针,将父类和子类的地址变成一样的地址。

4. 虽然最后一种比较麻烦,但是会惊奇的发现,如果是指针的话,可以实现父类中实现所有操作,子类只管创建对象和使用,子类如果想改实现,根据需要同名替代即可。甚至属性也可以写成函数指针那些,是一种非常灵活的使用方式,是一种上层设计模式的简单体现。

#include <iostream>
using namespace std;

class AAA {
public:
	AAA() {
		// YourVar = new int;
		// *YourVar = 10;
	}
	~AAA() {
		delete YourVar;
	}
	
	void print() {
		cout << "YourVar: " << *YourVar << endl;
	}
	
protected:
	int *YourVar;
};

class BBB : public AAA {
public:
	BBB() {
		YourVar = new int;
		// 将子类地址传递给父类
		AAA::YourVar = YourVar;
		*YourVar = 20;
	}
	~BBB() {}
	
	void print() {
		cout << "*********************" << endl;
		cout << "YourVar: " << *YourVar << endl;
		cout << "*********************" << endl;
	}
	
private:
	int *YourVar;
};

int main() {
	
	BBB b;
	b.print();
	
	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android Studio实现内容丰富的安卓图书馆座位图书预约系统

获取源码请点击文章末尾QQ名片联系&#xff0c;源码不免费&#xff0c;尊重创作&#xff0c;尊重劳动 项目编号109 1.开发环境android stuido jdk1.8 eclipse mysql tomcat 2.功能介绍 安卓端&#xff1a; 1.注册登录 2.查看公告 3.查看图书馆座位 4.查看图书馆图书&#xff0c…

Tcl学习笔记(一)——环境搭建及基本语法

一、Tcl简介 TCL&#xff08;Tool Command Language&#xff0c;即工具命令语言&#xff09;是一种解释执行的脚本语言。所谓解释执行语言&#xff0c;是指其不需要通过编译和联结&#xff0c;而是直接对每条语句进行顺序解释、执行。 TCL包含语言和工具库&#xff0c;TCL语言主…

开源数据集 nuScenes 之 3D Occupancy Prediction

数据总体结构 Nuscenes 数据结构 可以看一下我的blog如何下载完整版 mmdetection3d ├── mmdet3d ├── tools ├── configs ├── data │ ├── nuscenes │ │ ├── maps │ │ ├── samples │ │ ├── sweeps │ │ ├── lidarseg (o…

绝地求生:现在购买通行证还能兑换成长型武器吗?

大家好&#xff0c;我闲游盒&#xff0c;这几天收到几位盒友的私信咨询我现在购买通行证还能获得一把成长型武器吗&#xff1f;我相信还有许多盒友也有此困惑&#xff0c;那我就在这统一回复了&#xff0c;目前距通行证和商城物资箱礼包下架还有最后16天时间&#xff0c;众所周…

【Linux】从零开始认识进程 — 前篇

我从来不相信什么懒洋洋的自由。我向往的自由是通过勤奋和努力实现的更广阔的人生。。——山本耀司 从零开始认识进程 1 认识冯诺依曼体系2 操作系统3 进程3.1 什么是进程&#xff1f;&#xff1f;&#xff1f;3.2 进程管理PCB 3.3 Linux中的进程深入理解 3.4 进程创建总结 送给…

(一)Linux+Windows下安装ffmpeg

一丶前言 FFmpeg是一个开源的音视频处理工具集&#xff0c;由多个命令行工具组成。它可以在跨平台的环境中处理、转换、编辑和流媒体处理音视频文件。 FFmpeg支持多种常见的音视频格式和编解码器&#xff0c;可以对音视频文件进行编码、解码、转码、剪辑、合并等操作。它具有广…

如何在Tomcat中的webapp中手动发布

这里写目录标题 首先进入Tomcat文件夹进入webaaps中,编写Java代码最后进入浏览器打开就看可以进入这个界面了 首先进入Tomcat文件夹 如图: 进入webaaps中, 编写Java代码 最后进入浏览器打开 就看可以进入这个界面了

PX4|基于FAST-LIO mid360的无人机室内自主定位及定点悬停

目录 前言环境配置运行fast-lio修改px4位置信息融合方式编写位置坐标转换及传输节点 前言 在配置mid360运行环境后&#xff0c;可使用mid360进行室内的精准定位。 环境配置 在livox_ros_driver2的上级目录src下保存fast-lio的工程 git clone https://github.com/hku-mars/F…

AI短视频制作一本通:文本生成视频、图片生成视频、视频生成视频

第一部分&#xff1a;文本生成视频 1. 文本生成视频概述 随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;视频制作领域也迎来了创新的浪潮。文本生成视频是其中的一项令人激动的进展&#xff0c;它利用自然语言处理技术将文本内容转化为视频。这项技术在广…

redis和rabbitmq实现延时队列

redis和rabbitmq实现延时队列 延迟队列使用场景Redis中zset实现延时队列Rabbitmq实现延迟队列 延迟队列使用场景 1. 订单超时处理 延迟队列可以用于处理订单超时问题。当用户下单后&#xff0c;将订单信息放入延迟队列&#xff0c;并设置一定的超时时间。如果在超时时间内用户…

默写单词cpp(初学者版本)

笔摔坏了直接使用版:yum:仔细学习版:yum:1.直接使用版:yum:&#xff08;文件使用规范&#xff09;(1)文件(2)使用规范 2.仔细学习版。将会讲各个函数的功能和细节。今天太晚了&#xff0c;明天再写。 笔摔坏了 在一个阳光明媚的早晨&#xff0c;我愉快的奋笔疾书&#xff0c;抄…

基于VMware虚拟机安装MacOS BigSur系统

这周用VMWare搞了个MacOS虚拟机&#xff0c;也算是完成初中高中时候的梦想了吧~~&#xff08;那时候我的电脑配置还很拉跨&#xff0c;带不动虚拟机&#xff09;~~ 写一篇博客记录一下&#xff0c;当然这也是yonagi04.github.io建站的第一篇新博客 准备工作&#xff08;VMWare…

c++ 常用函数 集锦 整理中

c 常用函数集锦 目录 c 常用函数集锦 1、string和wstring之间转换 2、经纬度转 xyz 值 互转 3 、获取 根目录下的文件地址 1、string和wstring之间转换 std::string convertWStringToString(std::wstring wstr) {std::string str;if (!wstr.empty()){std::wstring_convert<…

31-Java前端控制器模式(Front Controller Pattern)

Java前端控制器模式 实现范例 前端控制器模式&#xff08;Front Controller Pattern&#xff09;是用来提供一个集中的请求处理机制&#xff0c;所有的请求都将由一个单一的处理程序处理该处理程序可以做认证/授权/记录日志&#xff0c;或者跟踪请求&#xff0c;然后把请求传给…

LabVIEW NV色心频率扫描

LabVIEW NV色心频率扫描 通过LabVIEW软件开发一个能够实现对金刚石氮空位&#xff08;Nitrogen-Vacancy&#xff0c;NV&#xff09;色心的频率扫描系统。系统通过USB协议与硬件设备通信&#xff0c;对NV色心进行高精度的频率扫描&#xff0c;满足了频率在2.6 GHz到3.2 GHz范围…

云原生:重塑未来应用的基石

随着数字化时代的不断深入&#xff0c;云原生已经成为了IT领域的热门话题。它代表着一种全新的软件开发和部署范式&#xff0c;旨在充分利用云计算的优势&#xff0c;并为企业带来更大的灵活性、可靠性和效率。今天我们就来聊一聊这个热门的话题&#xff1a;云原生~ &#x1f4…

DevEco Studio 项目创建

安装DevEco Studio后开始使用&#xff0c;双击桌面DevEco Studio 快捷方式弹出界面&#xff1a; 选择Application —> Empty Ability&#xff0c;点击Next 项目配置 Project name&#xff1a;工程的名称&#xff0c;可以自定义&#xff0c;由大小写字母、数字和下划线组成。…

解锁编程潜能:ChatGPT如何革新软件开发

目录 一、背景 二、功能描述 三、总结 一、背景 在这个飞速发展的数字时代&#xff0c;软件开发的效率和质量成了衡量一个开发者能力的重要标准。随着人工智能技术的不断进步&#xff0c;越来越多的开发者开始寻找能够提升工作效率的新方法。我就是其中之一&#xff0c;最近…

【RabbitMQ | 第一篇】消息队列基础知识

文章目录 1.消息队列基础知识1.1什么是消息队列&#xff1f;1.2消息队列有什么用&#xff1f;&#xff08;结合项目说&#xff09;1.2.1异步处理1.2.2削峰/限流1.2.3降低系统耦合性1.2.4实现分布式事务 1.3消息队列的缺点1.4JMS和AMQP1.4.1 JMS的两种消息模型&#xff08;1&…

海外社交营销为什么用云手机?不用普通手机?

海外社交营销作为企业拓展海外市场的重要手段&#xff0c;正日益受到企业的青睐。云手机以其成本效益和全球性特征&#xff0c;成为海外社交营销领域的得力助手。那么&#xff0c;究竟是什么特性使得越来越多的企业选择利用云手机进行海外社交营销呢&#xff1f;下文将对此进行…
最新文章