当前位置: 首页 > 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%就…...

C# 多窗口切换的实现

1、目的在主窗口中根据不同的按钮选择不同的子窗口显示。2、实现&#xff08;1&#xff09;、创建Winform窗体程序&#xff0c;放入SplitContainer控件splitContainer1将窗体分成左右2部分&#xff1b;&#xff08;2&#xff09;、在左侧splitContainer1.panel1中放入3个Button…...

【深度学习】RNN

1. 什么是RNN 循环神经网络&#xff08;Recurrent Neural Network, RNN&#xff09;是一类以序列&#xff08;sequence&#xff09;数据为输入&#xff0c;在序列的演进方向进行递归&#xff08;recursion&#xff09;且所有节点&#xff08;循环单元&#xff09;按链式连接的递…...

招聘岗位,机会难得

岗位需求 费话不多说&#xff0c;直接上JD&#xff1a; 嵌入式开发工程师&#xff1a; 17:411.计算机、通信等相关专业。 2.熟悉网络基础知识&#xff0c;熟悉802.11a/b/g/n/ac协议&#xff0c;能通过抓包等分析手段排查定位各种wifi相关问题。 3.熟悉路由器主要功能及实现原…...

web打印的几种方法(2023)

在工作中出现web打印的情况是非常多的&#xff0c;其实这也是一个比较烦人的问题&#xff0c;这篇博客整理一下关于Web打印的一些方法或者方式。 1. window.print() 这个方法是用来打印网页的&#xff0c;页面上的其他的元素也会被打印处理&#xff0c;在打印的时候页眉页脚是…...

代码随想录算法训练营day44 | 动态规划之完全背包 518. 零钱兑换 II 377. 组合总和 Ⅳ

day44完全背包基础知识问题描述举个栗子518. 零钱兑换 II1.确定dp数组以及下标的含义2.确定递推公式3.dp数组如何初始化4.确定遍历顺序5.举例推导dp数组377. 组合总和 Ⅳ1.确定dp数组以及下标的含义2.确定递推公式3.dp数组如何初始化4.确定遍历顺序5.举例来推导dp数组完全背包基…...

IntelliJ IDEA 实用插件推荐(包含使用教程)

IntelliJ IDEA 实用插件推荐 背景&#xff1a;电脑重装了&#xff0c;重新下载了最新版的IntelliJ IDEA&#xff0c;感觉默认模式有点枯燥&#xff0c;于是决定从网上下载一些实用美观的插件优化自己以后吃饭的工具&#xff0c;现在推荐的都是目前还能用的&#xff08;亲身实践…...

WideDeep模型

google提出的Wide&deep模型&#xff0c;将线性模型与DNN很好的结合起来&#xff0c;在提高模型泛化能力的同时&#xff0c;兼顾模型的记忆性。wide&deep这种将线性模型与DNN的并行连接模式&#xff0c;后来称为推荐领域的经典模式&#xff0c;奠定了后面深度学习模型的…...

nacos集群模式+keepalived搭建高可用服务

实际工作中如果nacos这样的核心服务停掉了或者整个服务器宕机了&#xff0c;那整个系统也就gg了&#xff0c;所以像这样的核心服务我们必须要搞个3个或者3个以上的nacos集群部署&#xff0c;实现高可用&#xff1b; 部署高可用版本之前&#xff0c;首先你要会部署单机版的naco…...

吉利「银河」负重突围

吉利控股集团最新公布的数据显示&#xff0c;2022年&#xff0c;吉利控股集团汽车总销量超230万辆&#xff0c;同比增长4.3%。其中&#xff0c;新能源汽车销量超64万辆&#xff0c;同比增长100.3%。 在中国本土市场&#xff0c;2022年吉利集团旗下品牌乘用车总交付量为135.84万…...

QT之图形视图框架概述——Graphics View Framework

QT之图形视图框架概述——Graphics View Framework1. 概述2. 核心类3. 事件传递4. Graphics View 坐标系统5. 参考1. 概述 Graphics View Framework是子Qt 4.2引入的&#xff0c;用来取代之前版本中的QCanvas。Graphics View Framework提拱了用于大量2D图形项的管理和交互的能…...

作文网站源码/百度的人工客服

近日荣耀手机CEO赵明在对于荣耀手机是否采用鸿蒙系统一事&#xff0c;做出了回应“荣耀会持续关注鸿蒙生态的发展&#xff0c;并且从消费者体验的角度选择最好的产品和解决方案”&#xff0c;媒体分析认为这意味着荣耀手机暂时不会考虑采用鸿蒙系统&#xff0c;而技术成熟、生态…...

金华网站开发公司/各大网站收录查询

RabbitMQ是消息队列。之前学过的队列queue&#xff1a;线程queue&#xff08;threading queue&#xff09;&#xff0c;只是多个线程之间进行数据交互。进程queue&#xff08;processing queue&#xff09;&#xff0c;只是父进程与子进程进行交互。两个独立的程序之间进行交互…...

中国化工第九建设公司网站/外链大全

1 背景 使用spring boot整合redis spring boot版本为 2.0.6.RELEASE 服务部署在Linux服务器 2 解决方案 登录自己服务部署的Linux服务器 首先查看自己主机名 hostname 输出 查看服务器配置文件 vim /etc/hosts加入如下配置即可...

深圳 b2c 网站建设/百度学术官网入口

一、AI可解释性 1.什么是可解释性&#xff1f; 可解释性&#xff0c;就是我们需要完成一件事的时候&#xff0c;我们能获取到的足够多的&#xff0c;能让我们自己理解的信息。当我们不能获得足够多的信息&#xff0c;来理解一件事情的时候&#xff0c;我们可以说这是不可解释…...

wordpress月份归档要收录吗/怎么弄自己的网站

Platform: Rockchip OS: Android 6.0 Kernel: 3.10.92 背景&#xff1a; Android M上有个新功能&#xff0c;就是外插的microSD卡&#xff0c;就可以当做Internal storage,也可以当做Portable storage(和之前版本作为external storag那样使用). External microSD Card做Int…...

平板上做网站的软件/上海网络seo公司

如果是开平方根可以使用函数 SQRT(number)&#xff0c;返回数值的平方根 比如SQRT(9) 计算返回3如果是开立方根或者n次方根&#xff0c;可以进e68a847a64364行幂运算&#xff0c;POWER(number,power)函数表示返回number数值的power次乘幂&#xff0c;如POWER(5,2)表示5的2次方&…...