c++父类转换为子类,子类转换为父类,子类父类指针相互强制转换

1.子类转换为父类

子类转换为父类之后,不能调用子类独有的函数和成员变量,只能调用子类继承的虚函数,利用

多态的特性。

#include <iostream>

class base {
public:
    virtual void Show()
    {
        std::cout << "base class" << std::endl;
    }
    int a = 1;
};

class Drived :public base
{
public:
    void Show()
    {
        std::cout << "A class" << std::endl;
    }

    void ShowA()
    {
        std::cout << "ShowA fun" << std::endl;
    }

    int b = 2;
    int c = 3;
};

int main()
{
    Drived* drive_class = new Drived();
    base* base_class = (base*)drive_class;
    base_class->Show(); //可以调用子类重写父类的虚函数
    //base_class->ShowA(); //不能调用子类的独有函数,会报错
    printf("%d\n", base_class->a); //可以调用父类独有的成员变量
    //printf("%d\n", B->b); //调用子类独有的成员变量会报错
    //printf("%d\n", B->c);
   
}

转换为父类指针之后,不能调用ShowA()函数,和子类的b,c成员变量。

只能调用Show()函数,和成员变量a

输出结果

2.父类转换为子类

父类转换为子类是会出现异常,因为子类比父类有更多的成员变量和函数。如果访问子类自己独有的成员变量,会访问到未知的地方。

2.1父类转换成子类,调用子类的成员变量。

#include <iostream>

class base {
public:
    virtual void Show()
    {
        std::cout << "base class" << std::endl;
    }
    int a = 1;
};

class Drived :public base
{
public:
    void Show()
    {
        std::cout << "A class" << std::endl;
    }

    void ShowA()
    {
        std::cout << "ShowA fun" << std::endl;
    }

    int b = 2;
    int c = 3;
};

int main()
{
    base* Base = new base();
 
    Drived* drive_class = (Drived*)Base;

    int m = drive_class->b; //这里b的值初始值是2,但是m的值却不是2.因为drive_class->b指向了未知的地方

    printf("%d", m);
   
}

这里b的值初始值是2,但是m的值却不是2.因为drive_class->b指向了未知的地方

2.2父类转换成子类,调用子类的成员函数。

#include <iostream>

class base {
public:
    virtual void Show()
    {
        std::cout << "base class" << std::endl;
    }
    int a = 1;
};

class Drived :public base
{
public:
    void Show()
    {
        std::cout << "A class" << std::endl;
    }

    void ShowA()
    {
        std::cout << "ShowA fun" << std::endl;
    }

    int b = 2;
    int c = 3;
};

int main()
{
    base* Base = new base();
 
    Drived* drive_class = (Drived*)Base;

    drive_class->Show();
    drive_class->ShowA();
   
}

输出结果

调用show()函数的时候调用的还是,父类的虚函数,原因是根本没有子类的实例化对象。

调用ShowA()函数的时候,能正常的调用,可能是因为,声明类Drived的时候,ShowA函数已经存在于 内存的全局代码段数据存储区了,成员函数和成员变量是不一样的。

Tips:所以上述这种父类转子类是不安全的转换,调用成员变量的时候,指向了未知的地方。

如果父类转子类的时候,实例化对象包含有子类的时候这种,转换才是安全的。

比如

#include <iostream>

class base {
public:
    virtual void Show()
    {
        std::cout << "base class" << std::endl;
    }
    int a = 1;
};

class Drived :public base
{
public:
    void Show()
    {
        std::cout << "A class" << std::endl;
    }

    void ShowA()
    {
        std::cout << "ShowA fun" << std::endl;
    }

    int b = 2;
    int c = 3;
};

int main()
{
    base* Base = new Drived();
 
    Drived* drive_class = (Drived*)Base;

    drive_class->Show();
    drive_class->ShowA();
    int m = drive_class->b;
    printf("%d", m);
   
}

输出结果

3.避免不安全的父类转换成子类

使用强制转换符dynamic_cast来避免不安全的强制转换

#include <iostream>

class base {
public:
    virtual void Show()
    {
        std::cout << "base class" << std::endl;
    }
    int a = 1;
};

class Drived :public base
{
public:
    void Show()
    {
        std::cout << "A class" << std::endl;
    }

    void ShowA()
    {
        std::cout << "ShowA fun" << std::endl;
    }

    int b = 2;
    int c = 3;
};

int main()
{
    base* Base = new Drived();
 
    Drived* drive_class = dynamic_cast<Drived*>(Base);
    if (drive_class != NULL)
    {
        printf("进入转换1");
        drive_class->Show();
        drive_class->ShowA();
        int m = drive_class->b;
        printf("%d", m);
        
    }

    Base = new base();
    drive_class = dynamic_cast<Drived*>(Base);
    
    if (drive_class != NULL)
    {
        printf("进入转换2");
        drive_class->Show();
        drive_class->ShowA();
        int m = drive_class->b;
        printf("%d", m);

    }
    
   
}

输出结果

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

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

相关文章

HDL Designer 2021.1 如何将默认编辑器修改为VsCode

第1步 安装Vscode 第2步 添加Vscode至HDL Designer 第3步 更改HDL Designer编译器 第4步 修改结束&#xff0c;在HDL Designer中双击block可使用Vscode编辑verilog

十分钟掌握前端获取实时数据的三种主流方式

前端获取实时数据的三种主流方式 本文聊聊前端获取实时数据的三种主要方式。想象一下&#xff0c;我们在网上购物时&#xff0c;经常能看到最新的优惠信息弹出&#xff0c;或者在社交媒体上看到朋友的最新动态更新。这些都是因为后端在默默地向我们的页面推送了最新的消息。那…

Oracle systemstate、gdb、dbx介绍

当数据库出现严重的性能问题或者hang了的时候&#xff0c; 可能最常用的办法就是重启数据库&#xff0c;简单有效解决问题&#xff1b;但是重启后如何追踪问题的根本原因成了难题&#xff0c;很多信息随着重启也消失不见了&#xff0c;让追查问题变的十分棘手&#xff0c;这时就…

LeetCode:9.回文数,对整数的反转操作

博主本想找个简单的题水一下&#xff0c;结果太久没写这块的代码&#xff0c;直接写着宕机着&#xff0c;十分难受&#xff0c;最后还调试了几下&#xff0c;悲&#xff0c; 目录 题目&#xff1a; 思路&#xff1a; 官方代码&#xff08;反转一半的&#xff09;&#xff1a…

如何在 Java 中通过 Map.Entry 访问 Map 的元素

我们使用 Map.Entry 来遍历 ConcurrentHashMap 的代码片段如下&#xff1a; for (Map.Entry<String, String> entry : map.entrySet()) { System.out.println("Key: " entry.getKey() ", Value: " entry.getValue()); } 在 Map.java 中&…

SpringBoot:配置相关知识点

SpringBoot&#xff1a;多环境配置 配置知识点demo&#xff1a;点击查看LearnSpringBoot02 点击查看更多的SpringBoot教程 一、SpringBootApplication SpringBootApplication 来标注一个主程序类&#xff0c;说明这是一个Spring Boot应用&#xff0c;运行这个类的main方法来…

挑战杯 python+opencv+机器学习车牌识别

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于机器学习的车牌识别系统 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;4分工作量&#xff1a;4分创新点&#xff1a;3分 该项目较为新颖&#xff0c;适…

ios设备解锁 --Apeaksoft iOS Unlocker

Apeaksoft iOS Unlocker是一款针对iOS系统的密码解锁工具。其主要功能包括解锁多种锁屏类型&#xff0c;包括数字密码、Touch ID、Face ID和自定义密码。此外&#xff0c;它还可以帮助用户删除iPhone密码以进入锁屏设备&#xff0c;忘记的Apple ID并将iPhone激活为新的&#xf…

【ARM Coresight 系列文章 8.1 - ARM Coresight 通过 APBIC arbiter】

请阅读【ARM Coresight SoC-400/SoC-600 专栏导读】 文章目录 APBIC arbiter仲裁使用举例APBIC arbiter 在 SoC-600中,APBIC 是用来为 APB4 master 和 APB4 slave 提供 连接关系的组件。APB 是一种简单的总线协议,通常用于低带宽或低性能外设,如定时器、接口控制等。APBIC …

Unity3d Shader篇(三)— 片元半兰伯特着色器解析

文章目录 前言一、片元半兰伯特着色器是什么&#xff1f;1. 片元漫反射着色器的工作原理2. 片元半兰伯特着色器的优缺点优点&#xff1a;缺点&#xff1a; 3. 公式 二、使用步骤1. Shader 属性定义2. SubShader 设置3. 渲染 Pass4. 定义结构体和顶点着色器函数5. 片元着色器函数…

java中String类常用API

前言&#xff1a;在学习java的String类的时候&#xff0c;有很多的API需要了解&#xff0c;下面我将举出其中在新手学习时使用频率较大的几个API。 先大体看一下有哪几个&#xff1a;&#xff08;如图&#xff09; 目录 1.equals&#xff08;&#xff09;和 equalsIgnoreCase&…

Linux环境下配置mysql主从复制

主从配置需要注意的地方 1、主DB server和从DB server数据库的版本一致 2、主DB server和从DB server数据库数据一致[这里就会可以把主的备份在从上还原&#xff0c;也可以直接将主的数据目录拷贝到从的相应数据目录] 3、主DB server开启二进制日志,主DB server和从DB serve…

「递归算法」:全排列

一、题目 给定一个不含重复数字的数组 nums &#xff0c;返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]示例 2&#xff1a; 输入&#xf…

【前端web入门第四天】02 CSS三大特性+背景图

文章目录: 1. CSS三大特性 1.1继承性 1.2 层叠性 1.3 优先级 1.3.1 优先级1.3.2 优先级-叠加计算规则 2. 背景图 2.1 背景属性2.2 背景图2.3 背景图的平铺方式2.4 背景图位置2.5 背景图缩放2.6 背景图固定2.7 背景复合属性 1. CSS三大特性 1.1继承性 什么是继承性? 子级默…

进阶C语言-通讯录的实现

通讯录 🎈1.设计要求🎈2.程序实现🔭2.1打印菜单及初始化通讯录🔭2.2显示所有联系人🔭2.3查找指定的联系人🔭2.4删除指定的联系人🔭2.5查找指定的联系人🔭2.6修改指定联系人🔭2.7按照年龄排序(以此为例)🎈3.全部源码以及实现🎈1.设计要求 🌞通过前面…

分享springboot框架的一个开源的本地开发部署教程(若依开源项目开发部署过程分享持续更新二开宝藏项目PostgresSQL数据库版)

1首先介绍下若依项目&#xff1a; 若依是一个基于Spring Boot和Spring Cloud技术栈开发的多租户权限管理系统。该开源项目提供了一套完整的权限管理解决方案&#xff0c;包括用户管理、角色管理、菜单管理、部门管理、岗位管理等功能。 若依项目采用前后端分离的架构&#xf…

3dmatch-toolbox详细安装教程-Ubuntu14.04

3dmatch-toolbox详细安装教程-Ubuntu14.04 前言docker搭建Ubuntu14.04安装第三方库安装cuda/cundnn安装OpenCV安装Matlab 安装以及运行3dmatch-toolbox1.安装测试3dmatch-toolbox(对齐两个点云) 总结 前言 paper:3DMatch: Learning Local Geometric Descriptors from RGB-D Re…

敏捷软件研发管理流程- scrum

Leangoo领歌是一款永久免费的专业的敏捷开发管理工具&#xff0c;提供端到端敏捷研发管理解决方案&#xff0c;涵盖敏捷需求管理、任务协同、进展跟踪、统计度量等。 Leangoo领歌上手快、实施成本低&#xff0c;可帮助企业快速落地敏捷&#xff0c;提质增效、缩短周期、加速创新…

【chromium】vs2022 中 clang构建

vs2022 “D:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\devenv.exe”看起来没装安装 clang 组件 vs2019 装的是12:报错了 Build started... 1>------ Build started: Project: ebBase, Configuration: Debug Win32 ------ 1>d:\Program Files…

数据结构(C语言)代码实现(七)——一元多项式的表示与相加

目录 前言 参考资料格式 头文件LinkList.h LocateElem函数&#xff0c;定位查找 有序插入&#xff08;没测试&#xff09; 完整代码 头文件polynomial.h 测试函数&#xff08;主函数&#xff09; 测试结果 前言 寒假在家&#xff0c;有点学不下去&#xff0c;写文章的…