• 记录C++类中的一次函数调用


    引用

    之前遇到一次函数调用结果的问题,今天在这里做一下记录。
    一个基类,一个派生类,两个类中都有一个函数名相同,参数相同,参数不同的函数,创建基类指针指向派生类对象,调用相应的函数,派生类指针指向基类对象,调用相应的函数,求其输出结果。
    具体看下面的示例。

    示例

    开发环境

    visual Studio 2017控制台输出程序。创建项目后自动生成相应的main.cpp文件,本文的代码全部都是在main.cpp中编写。

    示例代码

    main.cpp

    #include 
    using namespace std;
    
    class TransferBase 
    {
    public:
    	//int Fun() { cout << endl; }//无法重载仅按返回值区分的函数Fun()
    	void Fun() { cout << "TransferBase::Fun()" << endl; }
    	virtual void Fun(int a) { cout << "TransferBase::Fun(int a)" << endl; }
    private:
    };
    
    class TransferDerived :public TransferBase
    {
    public:
    	void Fun(int a) { cout << "TransferDerived::Fun(int a)" << endl; }//TransferDerived中的Fun(int a)与TransferBase中的Fun(int a)为多态,TransferDerived中的Fun(int a)与TransferBase中的Fun()为隐藏
    	void Fun() { cout << "TransferDerived::Fun()" << endl; }//TransferDerived中的Fun()函数与TransferBase中的Fun()函数为隐藏关系
    private:
    
    };
    
    int main()
    {
    	//类之间函数调用
    	TransferBase *pBase =  new TransferDerived;
    	TransferDerived *pDeri = dynamic_cast<TransferDerived*>(new TransferBase);//“dynamic_cast” : “TransferBase”不是多态类型	,基类指针转换为派生类指针的前提是基类必须有虚函数,否则编译错误;转换失败,派生类指针指向为nullptr
    
    	pBase->Fun();
    	pBase->Fun(2);
    	//pDeri为nullptr,未转换成功 
    	pDeri->Fun();//此句正常执行
    	pDeri->Fun(3);//pDeri为nullptr,此句崩溃???
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    上述的代码,使用dynamic_cast将基类指针强转为派生类指针失败,其指针pDeri为空,运行pDeri->Fun(3);时出现崩溃,但是为什么在执行pDeri->Fun();的时候能正常执行呢???
    原因:纯属意外。

    dynamic_cast使用注意事项

    1.用于类类型之间的强转。一般用于将基类指针转换为派生类指针,或将派生类指针转换为基类指针,但是将基类指针转换为派生类指针有一个前提:基类中必须要有虚函数
    2.指针强转失败,返回值为nullptr.
    上述main函数中创建派生类指针指向基类对象,一开始没有在基类中编写虚函数,因而编译的时候无法通过,在基类中增加了虚函数之后,TransferDerived pDeri = dynamic_cast>(new TransferBase);才能编译通过。但上述派生类指针指向依旧为空,也就是基类的对象并没有强转成功。
    其没转换成功的原因是:派生类继承自基类,含有基类的一些函数,可以自动转换为基类,而基类是不含有派生类中的函数,开辟的内存无法满足派生类的内存,直接访问会导致内存越界,故而无法直接转换为派生类。

    为了使基类的对象转换为派生类对象,这时需要做下面的一些修改。

    修改后的示例代码

    上述使用dynamic_cast后没有成功将基类对象转换为派生类对象,这里先将基类的指针指向派生类对象,后将指向派生类对象的指针强转为派生类指针。下面是改动后的代码:

    int main()
    {
    //类之间函数调用
    	TransferBase *pBase =  new TransferDerived;
    	TransferDerived *pDeri = dynamic_cast<TransferDerived*>(new TransferBase);//“dynamic_cast” : “TransferBase”不是多态类型	,基类指针转换为派生类指针的前提是基类必须有虚函数,否则编译错误;转换失败,派生类指针指向为nullptr
    
    	//使基类指针转换为派生类指针转换成功——先将基类指针指向派生类对象,再将基类指针转换为派生类指针
    	TransferDerived derive;
    	TransferBase *base = &derive;
    	pDeri = dynamic_cast<TransferDerived*>(base);//pDeri不为nullptr,基类指针转换为派生类指针成功
    
    	//转换成功,pDeri不为nullptr
    	pBase->Fun();
    	pBase->Fun(2);
    	pDeri->Fun();
    	pDeri->Fun(3);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    运行结果

    在这里插入图片描述

    总结

    上述涉及到的知识点:
    1.虚函数的使用;
    2.隐藏、重载、重写的区别;
    3.数据强转dynamic_cast.
    以上是此篇文章需要具备的知识点。本文仅以记录。有关隐藏、重载、重写的介绍可以查看我之前的文章进行了解。

  • 相关阅读:
    【线性代数及其应用 —— 第一章 线性代数中的线性方程组】-1.线性方程组
    某电商网站的数据库设计(4)——创建各个基础表之间的关联视图
    寄存器、缓存、内存(虚拟、物理地址)、DDR、RAM的关系
    vue 按钮权限
    使用软引用实现缓存机制
    一、CSS浮动
    React + Springboot + Quartz,从0实现Excel报表自动化
    基于混沌搜索策略的鲸鱼优化算法-附代码
    Spark/Hive 行列转换
    音乐播放器APP
  • 原文地址:https://blog.csdn.net/blqzj214817/article/details/126732670