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

news/2024/9/6 6:09:26 标签: 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);

    }
    
   
}

输出结果


http://www.niftyadmin.cn/n/5374317.html

相关文章

【深度优先搜索】【树】【图论】2973. 树中每个节点放置的金币数目

作者推荐 视频算法专题 本博文涉及知识点 深度优先搜索 树 图论 分类讨论 LeetCode2973. 树中每个节点放置的金币数目 给你一棵 n 个节点的 无向 树&#xff0c;节点编号为 0 到 n - 1 &#xff0c;树的根节点在节点 0 处。同时给你一个长度为 n - 1 的二维整数数组 edges…

JavaScript 设计模式之外观模式

外观模式 我们为啥要使用外观模式呢&#xff0c;其实我们在使用各种 js 库的时候常常会看到很多的外观者模式&#xff0c;也正是这些库的大量使用&#xff0c;所以使得兼容性更广泛&#xff0c;通过外观者模式来封装多个功能&#xff0c;简化底层操作方法 const A {g: functi…

FAST角点检测算法

FAST&#xff08;Features from Accelerated Segment Test&#xff09;角点检测算法是一种快速且高效的角点检测方法。它通过检测每个像素周围的连续像素集合&#xff0c;确定是否为角点。以下是 FAST 角点检测算法的基本流程&#xff1a; FAST 角点检测算法的基本过程主要包括…

【Django】Django文件上传

文件上传 1 定义&场景 定义&#xff1a;用户可以通过浏览器将图片等文件上传至网站。 场景&#xff1a; 用户上传头像。 上传流程性的文档[pdf&#xff0c;txt等] 2 上传规范-前端[html] 文件上传必须为POST提交方式 表单 <form> 中文件上传时必须带有 enctype…

无缝畅享稀土掘金社区:SpringBoot、Docker、阿里云助力自动签到与抽奖脚本的创新实现

创建一个SpringBoot项目 添加依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.s…

Python高级进阶--多线程爬取下载小说(基于笔趣阁的爬虫程序)

目录 一、前言 1、写在前面 2、本帖内容 二、编写代码 1、抓包分析 a、页面分析 b、明确需求 c、抓包搜寻 2、编写爬虫代码 a、获取网页源代码 b、提取所有章节的网页源代码 c、下载每个章节的小说 d、 清洗文件名 e、删除子文件夹 f、将下载的小说的所有txt文件…

[C/C++] -- JSON for Modern C++

JSON for Modern C&#xff08;nlohmann/json&#xff09;是一个流行的 C JSON 库&#xff0c;由德国开发者nlohmann编写。这个库提供了简洁而灵活的 API&#xff0c;使得在C中解析和生成JSON数据变得非常方便。 1.JSON简介 JSON&#xff08;JavaScript Object Notation&…

C语言中的作用域与生命周期

作用域&#xff08;scope&#xff09;是程设计概念&#xff0c;通常来说&#xff0c;一段程序代码中所⽤到的名字并不总是有效的&#xff0c;而限定这个名字的可⽤性的代码范围就是这个名字的作用域。 局部变量的作用域是变量所在的局部范围。全局变量的作用域是整个工程&…