引用
之前遇到一次函数调用结果的问题,今天在这里做一下记录。
一个基类,一个派生类,两个类中都有一个函数名相同,参数相同,参数不同的函数,创建基类指针指向派生类对象,调用相应的函数,派生类指针指向基类对象,调用相应的函数,求其输出结果。
具体看下面的示例。
示例
开发环境
visual Studio 2017控制台输出程序。创建项目后自动生成相应的main.cpp文件,本文的代码全部都是在main.cpp中编写。
示例代码
main.cpp
#include <iostream>
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”不是多态类型 ,基类指针转换为派生类指针的前提是基类必须有虚函数,否则编译错误;转换失败,派生类指针指向为nullptrpBase->Fun();pBase->Fun(2);//pDeri为nullptr,未转换成功 pDeri->Fun();//此句正常执行pDeri->Fun(3);//pDeri为nullptr,此句崩溃???
}
上述的代码,使用dynamic_cast将基类指针强转为派生类指针失败,其指针pDeri为空,运行pDeri->Fun(3);时出现崩溃,但是为什么在执行pDeri->Fun();的时候能正常执行呢???
原因:纯属意外。
dynamic_cast使用注意事项
1.用于类类型之间的强转。一般用于将基类指针转换为派生类指针,或将派生类指针转换为基类指针,但是将基类指针转换为派生类指针有一个前提:基类中必须要有虚函数;
2.指针强转失败,返回值为nullptr.
上述main函数中创建派生类指针指向基类对象,一开始没有在基类中编写虚函数,因而编译的时候无法通过,在基类中增加了虚函数之后,TransferDerived pDeri = dynamic_cast<TransferDerived>(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不为nullptrpBase->Fun();pBase->Fun(2);pDeri->Fun();pDeri->Fun(3);
}
运行结果
总结
上述涉及到的知识点:
1.虚函数的使用;
2.隐藏、重载、重写的区别;
3.数据强转dynamic_cast.
以上是此篇文章需要具备的知识点。本文仅以记录。有关隐藏、重载、重写的介绍可以查看我之前的文章进行了解。