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

C++将派生类赋值给基类(向上转型)

1.将派生类对象赋值给基类对象

#include <iostream>
using namespace std;//基类
class A{
public:A(int a);
public:void display();
public:int m_a;
};
A::A(int a): m_a(a){ }
void A::display(){cout<<"Class A: m_a="<<m_a<<endl;
}//派生类
class B: public A{
public:B(int a, int b);
public:void display();
public:int m_b;
};
B::B(int a, int b): A(a), m_b(b){ }
void B::display(){cout<<"Class B: m_a="<<m_a<<", m_b="<<m_b<<endl;
}int main(){A a(10);B b(66, 99);//赋值前a.display();b.display();cout<<"--------------"<<endl;//赋值后a = b;a.display();b.display();return 0;
}

运行结果:

Class A: m_a=10
Class B: m_a=66, m_b=99
'----------------------------
Class A: m_a=66
Class B: m_a=66, m_b=99
在这里插入图片描述

2.将派生类指针赋值给基类指针

#include <iostream>
using namespace std;//基类A
class A{
public:A(int a);
public:void display();
protected:int m_a;
};
A::A(int a): m_a(a){ }
void A::display(){cout<<"Class A: m_a="<<m_a<<endl;
}//中间派生类B
class B: public A{
public:B(int a, int b);
public:void display();
protected:int m_b;
};
B::B(int a, int b): A(a), m_b(b){ }
void B::display(){cout<<"Class B: m_a="<<m_a<<", m_b="<<m_b<<endl;
}//基类C
class C{
public:C(int c);
public:void display();
protected:int m_c;
};
C::C(int c): m_c(c){ }
void C::display(){cout<<"Class C: m_c="<<m_c<<endl;
}//最终派生类D
class D: public B, public C{
public:D(int a, int b, int c, int d);
public:void display();
private:int m_d;
};
D::D(int a, int b, int c, int d): B(a, b), C(c), m_d(d){ }
void D::display(){cout<<"Class D: m_a="<<m_a<<", m_b="<<m_b<<", m_c="<<m_c<<", m_d="<<m_d<<endl;
}int main(){A *pa = new A(1);B *pb = new B(2, 20);C *pc = new C(3);D *pd = new D(4, 40, 400, 4000);pa = pd;pa -> display();pb = pd;pb -> display();pc = pd;pc -> display();cout<<"-----------------------"<<endl;cout<<"pa="<<pa<<endl;cout<<"pb="<<pb<<endl;cout<<"pc="<<pc<<endl;cout<<"pd="<<pd<<endl;return 0;
}

运行结果:

Class A: m_a=4
Class B: m_a=4, m_b=40
Class C: m_c=400
'-----------------------
pa=0x9b17f8
pb=0x9b17f8
pc=0x9b1800
pd=0x9b17f8

本例中定义了多个对象指针,并尝试将派生类指针赋值给基类指针。与对象变量之间的赋值不同的是,对象指针之间的赋值并没有拷贝对象的成员,也没有修改对象本身的数据,*仅仅是改变了指针的指向*。
3.virtual实现多态

#include <iostream>
using namespace std;//基类People
class People{
public:People(char *name, int age);void display();
protected:char *m_name;int m_age;
};
People::People(char *name, int age): m_name(name), m_age(age){}
void People::display(){cout<<m_name<<"今年"<<m_age<<"岁了,是个无业游民。"<<endl;
}//派生类Teacher
class Teacher: public People{
public:Teacher(char *name, int age, int salary);void display();
private:int m_salary;
};
Teacher::Teacher(char *name, int age, int salary): People(name, age), m_salary(salary){}
void Teacher::display(){cout<<m_name<<"今年"<<m_age<<"岁了,是一名教师,每月有"<<m_salary<<"元的收入。"<<endl;
}int main(){People *p = new People("王志刚", 23);p -> display();p = new Teacher("赵宏佳", 45, 8200);p -> display();return 0;
}

在这里插入图片描述

#include <iostream>
using namespace std;//基类People
class People{
public:People(char *name, int age);virtual void display();  //声明为虚函数
protected:char *m_name;int m_age;
};
People::People(char *name, int age): m_name(name), m_age(age){}
void People::display(){cout<<m_name<<"今年"<<m_age<<"岁了,是个无业游民。"<<endl;
}//派生类Teacher
class Teacher: public People{
public:Teacher(char *name, int age, int salary);virtual void display();  //声明为虚函数
private:int m_salary;
};
Teacher::Teacher(char *name, int age, int salary): People(name, age), m_salary(salary){}
void Teacher::display(){cout<<m_name<<"今年"<<m_age<<"岁了,是一名教师,每月有"<<m_salary<<"元的收入。"<<endl;
}int main(){People *p = new People("王志刚", 23);p -> display();p = new Teacher("赵宏佳", 45, 8200);p -> display();return 0;
}

在这里插入图片描述
4.多态例子:

#include <iostream>
using namespace std;//军队
class Troops{
public:virtual void fight(){ cout<<"Strike back!"<<endl; }
};//陆军
class Army: public Troops{
public:void fight(){ cout<<"--Army is fighting!"<<endl; }
};
//99A主战坦克
class _99A: public Army{
public:void fight(){ cout<<"----99A(Tank) is fighting!"<<endl; }
};
//武直10武装直升机
class WZ_10: public Army{
public:void fight(){ cout<<"----WZ-10(Helicopter) is fighting!"<<endl; }
};
//长剑10巡航导弹
class CJ_10: public Army{
public:void fight(){ cout<<"----CJ-10(Missile) is fighting!"<<endl; }
};//空军
class AirForce: public Troops{
public:void fight(){ cout<<"--AirForce is fighting!"<<endl; }
};
//J-20隐形歼击机
class J_20: public AirForce{
public:void fight(){ cout<<"----J-20(Fighter Plane) is fighting!"<<endl; }
};
//CH5无人机
class CH_5: public AirForce{
public:void fight(){ cout<<"----CH-5(UAV) is fighting!"<<endl; }
};
//轰6K轰炸机
class H_6K: public AirForce{
public:void fight(){ cout<<"----H-6K(Bomber) is fighting!"<<endl; }
};int main(){Troops *p = new Troops;p ->fight();//陆军p = new Army;p ->fight();p = new _99A;p -> fight();p = new WZ_10;p -> fight();p = new CJ_10;p -> fight();//空军p = new AirForce;p -> fight();p = new J_20;p -> fight();p = new CH_5;p -> fight();p = new H_6K;p -> fight();return 0;
}

在这里插入图片描述
5.dynamic_cast 关键字
dynamic_cast 用于在类的继承层次之间进行类型转换,它既允许向上转型(Upcasting),也允许向下转型(Downcasting)。向上转型是无条件的,不会进行任何检测,所以都能成功;向下转型的前提必须是安全的,要借助 RTTI 进行检测,所有只有一部分能成功。
5.1.向上转型(Upcasting)
向上转型时,只要待转换的两个类型之间存在继承关系,并且基类包含了虚函数(这些信息在编译期间就能确定),就一定能转换成功。因为向上转型始终是安全的,所以 dynamic_cast 不会进行任何运行期间的检查,这个时候的 dynamic_cast 和 static_cast 就没有什么区别了。

#include <iostream>
#include <iomanip>
using namespace std;class Base{
public:Base(int a = 0): m_a(a){ }int get_a() const{ return m_a; }virtual void func() const { }
protected:int m_a;
};class Derived: public Base{
public:Derived(int a = 0, int b = 0): Base(a), m_b(b){ }int get_b() const { return m_b; }
private:int m_b;
};int main(){//情况①Derived *pd1 = new Derived(35, 78);Base *pb1 = dynamic_cast<Derived*>(pd1);cout<<"pd1 = "<<pd1<<", pb1 = "<<pb1<<endl;cout<<pb1->get_a()<<endl;	//OKcout<<pb1->get_b()<<endl;	//NGcout<<pd1->get_b()<<endl;	//OKpb1->func();return 0;
}

5.2.向下转型(Downcasting)
向下转型是有风险的,dynamic_cast 会借助 RTTI 信息进行检测,确定安全的才能转换成功,否则就转换失败。那么,哪些向下转型是安全地呢,哪些又是不安全的呢?下面我们通过一个例子来演示:

#include <iostream>
using namespace std;class A{
public:virtual void func() const { cout<<"Class A"<<endl; }
private:int m_a;
};class B: public A{
public:virtual void func() const { cout<<"Class B"<<endl; }
private:int m_b;
};class C: public B{
public:virtual void func() const { cout<<"Class C"<<endl; }
private:int m_c;
};class D: public C{
public:virtual void func() const { cout<<"Class D"<<endl; }
private:int m_d;
};int main(){A *pa = new A();B *pb;C *pc;//情况①pb = dynamic_cast<B*>(pa);  //向下转型失败if(pb == NULL){cout<<"Downcasting failed: A* to B*"<<endl;}else{cout<<"Downcasting successfully: A* to B*"<<endl;pb -> func();}pc = dynamic_cast<C*>(pa);  //向下转型失败if(pc == NULL){cout<<"Downcasting failed: A* to C*"<<endl;}else{cout<<"Downcasting successfully: A* to C*"<<endl;pc -> func();}cout<<"-------------------------"<<endl;//情况②pa = new D();  //向上转型都是允许的pb = dynamic_cast<B*>(pa);  //向下转型成功if(pb == NULL){cout<<"Downcasting failed: A* to B*"<<endl;}else{cout<<"Downcasting successfully: A* to B*"<<endl;pb -> func();}pc = dynamic_cast<C*>(pa);  //向下转型成功if(pc == NULL){cout<<"Downcasting failed: A* to C*"<<endl;}else{cout<<"Downcasting successfully: A* to C*"<<endl;pc -> func();}return 0;
}

在这里插入图片描述

在这里插入图片描述

相关文章:

C++将派生类赋值给基类(向上转型)

1.将派生类对象赋值给基类对象 #include <iostream> using namespace std;//基类 class A{ public:A(int a); public:void display(); public:int m_a; }; A::A(int a): m_a(a){ } void A::display(){cout<<"Class A: m_a"<<m_a<<endl; }//…...

使用Platform Designer创建Nios II 最小系统

Nios II简介 ​ Nios II 软核处理器十多年前就有了&#xff0c;它和xilinx的MicroBlaze类似&#xff0c;性能相比硬核处理器要差得多&#xff0c;工程应用也不是很多&#xff0c;那还有必须学习一下吗&#xff1f;我个人认为了解一下Nios II开发流程&#xff0c;对intel FPGA开…...

CD销售管理系统

技术&#xff1a;Java、JSP等摘要&#xff1a;二十一世纪是一个集数字化&#xff0c;网络化&#xff0c;信息化的&#xff0c;以网络为核心的社会。中国的网民充分领略到“畅游天地间&#xff0c;网络无极限” 所带来的畅快。随着Internet的飞速发展&#xff0c;使得网络的应用…...

华为OD机试模拟题 用 C++ 实现 - 玩牌高手(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 最多获得的短信条数(2023.Q1)) 文章目录 最近更新的博客使用说明玩牌高手题目输入输出描述示例一输入输出说明Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为…...

Hive 的Stage如何划分?

Hive 的Stage如何划分&#xff0c;也是Hive SQL需要优化的一个点&#xff0c;这个问题&#xff0c;我也是在实际的工作中遇到的。所以我查询了网络的解答并记录下来&#xff0c;以便日后复习。以下是主要内容&#xff0c;enjoy~~~ 一个 Hive 任务会包含一个或多个 stage&#…...

《嵌入式应用开发》实验一、开发环境搭建与布局(上)

1. 搭建开发环境 去官网&#xff08;https://developer.android.google.cn/studio&#xff09;下载 Android Studio。 安装SDK&#xff08;默认Android 7.0即可&#xff09; 全局 gradle 镜像配置 在用户主目录下的 .gradle 文件夹下面新建文件 init.gradle&#xff0c;内容为…...

电子科技大学软件工程期末复习笔记(五):生产率和工作度量

目录 前言 重点一览 软件产品度量 测量软件生产率的两种方法 基于LOC测量 例题&#xff1a; 优点 缺点 基于功能点测量 例题&#xff1a; 本章小结 前言 本复习笔记基于王玉林老师的课堂PPT与复习大纲&#xff0c;供自己期末复习与学弟学妹参考用。 重点一览 这一部分内…...

400G光模块知识大全

400G光模块是目前高速传输领域中的一种先进产品&#xff0c;被广泛应用于高性能数据中心、通信网络、大规模计算、云计算等领域。本文将从400G光模块的定义、技术、产品型号、应用场景以及未来发展方向进行详细介绍。一、什么是400G光模块&#xff1f;400G光模块是指传输速率达…...

【Linux】零成本在家搭建自己的私人服务器解决方案

我这个人自小时候以来就特喜欢永久且免费的东西&#xff0c;也因此被骗过&#xff08;花巨款买了永久超级会员最后就十几天&#xff09;。 长大后骨子里也是喜欢永久且免费的东西&#xff0c;所以我不买服务器&#xff0c;用GitHubPage或者GiteePage搭建自己的静态私人博客&…...

Python 多线程、多进程和协程

一、多线程 threading 模块 threading 模块对象 对象描述Thread表示一个执行线程的对象Lock锁原语对象&#xff08;与 thread 模块中的锁一样&#xff09;RLock可重入锁对象&#xff0c;使单一线程可以&#xff08;再次&#xff09;获得已持有的锁&#xff08;递归锁&#x…...

Xml 注解

文章目录XmlRootElement(name"MyRootElement")XmlAccessorType(XmlAccessType.FIELD)XmlElementXmlAttributeXmlValueXmlElementRefXmlRootElement(name“MyRootElement”) XmlRootElement(name"MyRootElement") public class AccessorType {public Strin…...

【CSS文字滚动】CSS实现文字横向循环无缝滚动,鼠标移入暂停移出继续(附实测源码)

CSS如何实现文字横向滚动滚动效果1、垃圾liMarquee&#xff08;最好别用&#xff09;2、css实现文字滚动&#xff0c;且鼠标移入移出暂停和继续HTML源码如下&#xff1a;CSS源码如下&#xff1a;JS源码如下&#xff1a;3、片尾彩蛋CSS实现文字横向循环无缝滚动&#xff0c;鼠标…...

不使用implements关键字实现实现类(类似于mapper)

首先&#xff0c;说明一下功能需求&#xff0c;平时定义一个接口&#xff0c;就要使用implements关键字来实现接口。那么&#xff0c;当不使用此关键字的时候&#xff0c;是否也能使相关接口也能够绑定实现类呢&#xff1f; 答案是肯定的。 此篇文章的主要功能有两个&#xf…...

antd4里table的滚动是如何实现的?

rc-table里Header、Footer、TableBody实现保持同频滚动的方法 场景&#xff1a;Header、Footer都有&#xff0c;Table设置了scrollX&#xff0c;才关注同频滚动 那么是如何实现的&#xff1f; 监听onScroll方法获取到滚动条向左的滚动的距离scrollLeft&#xff1b;同时给三个…...

抓取namenode 50070 jmx的指标信息

在生产实践过程中&#xff0c;需要把data退役之后需要停机下线&#xff0c;在下线之前需要确认机器是否已下线完成&#xff0c;要去namenode的50070界面上查看显然效率低&#xff0c;为了能够快速拿到节点信息&#xff0c;写了简单的脚本。jmx/50070还有很多信息可以获取&#…...

aspnetcore-browser-refresh.js和Visual Studio Browser Link

我在调试ASP.NET Core web应用时&#xff0c;发现请求的页面文档底部多了一部分文件&#xff0c;而在我的页面中却没有包含&#xff0c;故查询资料&#xff0c;在此记录&#xff1a; 图中&#xff0c;可以看到红框部分是多出来了2个脚本 1.aspnetcore-browser-refresh.js 这里…...

hadoop 集群常用命令(学习笔记) —— 筑梦之路

概念介绍 #HDFS 概述Hadoop Distributed File System&#xff0c;简称HDFS&#xff0c;是一个分布式文件系统。&#xff08;1&#xff09;NameNode&#xff08;nn&#xff09;&#xff1a;存储文件的元数据&#xff0c;如文件名&#xff0c;文件目录结构&#xff0c;文件属性&…...

ARC142D Deterministic Placing

ARC142D Deterministic Placing 题目大意 有一棵nnn个顶点的树&#xff0c;每个点上最多放一张卡片&#xff0c;你可以做如下操作&#xff1a; 同时将所有的卡片移到它所在顶点的相邻的一个顶点上 一个操作我们说它是好的&#xff0c;当下列条件满足&#xff1a; 每条边最…...

阶段八:服务框架高级(第二章:分布式事务)

阶段八&#xff1a;服务框架高级&#xff08;第二章&#xff1a;分布式事务&#xff09;Day-分布式事务0.学习目标1.分布式事务问题1.1.本地事务1.2.分布式事务1.3.演示分布式事务问题2.理论基础2.1.CAP定理2.1.1.一致性2.1.2.可用性2.1.3.分区容错2.1.4.矛盾2.2.BASE理论2.3.解…...

RPC异步化原理

深入RPC&#xff0c;更好使用RPC&#xff0c;须从RPC框架整体性能考虑问题。得知道如何提升RPC框架的性能、稳定性、安全性、吞吐量及如何在分布式下快速定位问题。RPC框架如何压榨单机吞吐量&#xff1f; 1 前言 TPS一直上不去&#xff0c;压测时CPU压到40%&#xff5e;50%就…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

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

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

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

安卓基础(aar)

重新设置java21的环境&#xff0c;临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的&#xff1a; MyApp/ ├── app/ …...

【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制

使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下&#xff0c;限制某个 IP 的访问频率是非常重要的&#xff0c;可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案&#xff0c;使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

R 语言科研绘图第 55 期 --- 网络图-聚类

在发表科研论文的过程中&#xff0c;科研绘图是必不可少的&#xff0c;一张好看的图形会是文章很大的加分项。 为了便于使用&#xff0c;本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中&#xff0c;获取方式&#xff1a; R 语言科研绘图模板 --- sciRplothttps://mp.…...

PHP 8.5 即将发布:管道操作符、强力调试

前不久&#xff0c;PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5&#xff01;作为 PHP 语言的又一次重要迭代&#xff0c;PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是&#xff0c;借助强大的本地开发环境 ServBay&am…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域&#xff0c;无损检测&#xff08;NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统&#xff0c;以非接触式光学麦克风技术为核心&#xff0c;打破传统检测瓶颈&#xff0c;为半导体、航空航天、汽车制造等行业提供了高灵敏…...

永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器

一、原理介绍 传统滑模观测器采用如下结构&#xff1a; 传统SMO中LPF会带来相位延迟和幅值衰减&#xff0c;并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF)&#xff0c;可以去除高次谐波&#xff0c;并且不用相位补偿就可以获得一个误差较小的转子位…...