先来看一个例子:
#include "pch.h"
#include <iostream>
using namespace std;
class human
{
public:
void fun() { }
virtual void eat() { }
human()
{
cout << "human()" << endl;
}
~human()
{
cout << "~human()" << endl;
}
};
class man :public human
{
public:
void eat() { cout << "面食" << endl; };
man()
{
cout << "man()" << endl;
}
~man()
{
cout << "~man()" << endl;
}
void test()
{
cout << "void test()" << endl;
}
};
int main()
{
human *phuman = new man;
//phuman->test();错误
return 0;
}
上述例子中,phuman无法调用man类的test函数,那
有什么办法可以调用吗?也许你会说,我在父类中也定义一个test函数,然后也声明从虚函数不就行了,
但是,这样很麻烦,我为了用一个父类指针调用一个子类的函数,还要额外多写一个test函数不是太麻烦了吗?答案是有办法可以解决这个问题,要用RTTI
技术就可以了,也就是接下来要讲的话题。
一:RTTI
运行时类型识别,可以看成是系统提供的一种能力。
有两个运算符组成。
dynamic_cast和typeid
二:dynamic_cast
#include "pch.h"
#include <iostream>
using namespace std;
class A
{
public:
A() { }
virtual ~A() { }
};
class B :public A
{
public:
B() { }
void test() { }
virtual ~B() { }
};
class C :public B
{
public:
C() { }
virtual ~C() { }
};
class D:public B
{
public:
D() { }
virtual ~D() { }
};
int main()
{
//指针类型的转换,如果转换不成功,会等于nullptr
B *pb = new B;
C *pc = dynamic_cast<C *>(pb); //转换不成功
if (pc == nullptr)
{
cout << "转换不成功" << endl;
}
A *pa = new B; //这个时候pa并不可以操作test函数
B *pb1 = dynamic_cast<B *>(pa);
if (pb1 != nullptr) //
{
cout << "转换成功" << endl;
pb1->test();//这个时候就可以操作test函数了
}
//引用类型的转换
A *a = new B;
A &q = *a;
try
{
B &b = dynamic_cast<B&>(q);//如果转换成功会继续往下执行
b.test();
}
catch (bad_cast)
{
//转换不成功会抛出异常
}
return 0;
}
说明:
dynamic_cast运算符使用方法
dynamic_cast<type*>(e)
dynamic_cast<type&>(e)
dynamic_cast<type&&>(e)
要想转换成功,必须保证基类当中含有虚函数。
三:typeid运算符