之前遇到一次函数调用结果的问题,今天在这里做一下记录。
一个基类,一个派生类,两个类中都有一个函数名相同,参数相同,参数不同的函数,创建基类指针指向派生类对象,调用相应的函数,派生类指针指向基类对象,调用相应的函数,求其输出结果。
具体看下面的示例。
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,此句崩溃???
}
上述的代码,使用dynamic_cast将基类指针强转为派生类指针失败,其指针pDeri为空,运行pDeri->Fun(3);时出现崩溃,但是为什么在执行pDeri->Fun();的时候能正常执行呢???
原因:纯属意外。
1.用于类类型之间的强转。一般用于将基类指针转换为派生类指针,或将派生类指针转换为基类指针,但是将基类指针转换为派生类指针有一个前提:基类中必须要有虚函数;
2.指针强转失败,返回值为nullptr.
上述main函数中创建派生类指针指向基类对象,一开始没有在基类中编写虚函数,因而编译的时候无法通过,在基类中增加了虚函数之后,TransferDerived pDeri = dynamic_cast
其没转换成功的原因是:派生类继承自基类,含有基类的一些函数,可以自动转换为基类,而基类是不含有派生类中的函数,开辟的内存无法满足派生类的内存,直接访问会导致内存越界,故而无法直接转换为派生类。
为了使基类的对象转换为派生类对象,这时需要做下面的一些修改。
上述使用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.数据强转dynamic_cast.
以上是此篇文章需要具备的知识点。本文仅以记录。有关隐藏、重载、重写的介绍可以查看我之前的文章进行了解。