RTTI —— 运行阶段类型识别
1.多态
- 定义:允许将子类类型的指针赋值给父类类型的指针。多态性在Object Pascal和C++中都是通过虚函数(Virtual Function) 实现的。
- 无多态性示例
class Base
{
public:
Base(){}
void FunOne(){std::cout << "This is Base" << std::endl;}
};
class SubOne : public Base
{
public:
SubOne(){}
void FunOne(){std::cout << "This is SubOne" << std::endl;}
};
运行结果:
2.多态性示例
class Base
{
public:
Base(){}
virtual ~Base() {}
virtual void FunOne(){std::cout << "This is Base" << std::endl;}
};
class SubOne : public Base
{
public:
SubOne(){}
~SubOne()override {}
void FunOne() override {std::cout << "This is SubOne" << std::endl;}
};
运行结果:
2.运行阶段类型识别
运行阶段类型识别运用于继承时需要派生类具有多态性 <==> 必须实现一个或多个虚函数
1.dynamic_cast
功能:将指向派生类对象的父类指针转换为派生类指针,转换失败返回nullptr
使用示例:
int main()
{
Base *pBase = new Base;
Base *pSub = new SubOne;
SubOne *pSub2 = new SubOne;
SubOne *pDyname1 = dynamic_cast<SubOne*>(pSub);
if(nullptr == pDyname1)
{
std::cout << "pDyname1 dynamic_cast fail" << std::endl;
}
else
{
std::cout << "pDyname1 dynamic_cast success" << std::endl;
}
SubOne *pDyname2 = dynamic_cast<SubOne*>(pBase);
if(nullptr == pDyname2)
{
std::cout << "pDyname2 dynamic_cast fail" << std::endl;
}
else
{
std::cout << "pDyname2 dynamic_cast success" << std::endl;
}
}
运行结果:
2.typeid和type_info
typeid运算符返回一个type_info类型的对象的引用,typeid可以应用于任何类型或具有该类型的任何表达式。
type_info类头文件为#include <typeinfo.h>,此类重载了 != 和 == 一般会实现name()函数返回一个随实现而不同的字符串。c++中还实现了before();原型如下:
const char* name() const;
//可用于判断继承类型
bool before (const type_info& rhs) const;
使用示例:
int main()
{
double dbParam = 2.2;
int iParam = 1;
Base *pNull = nullptr;
Base *pBase = new Base;
Base *pSub = new SubOne;
SubOne *pSub2 = new SubOne;
if(typeid (double) == typeid (dbParam))
{
std::cout << "dbParam is double type" << "\tname = " << typeid (dbParam).name() << std::endl;
}
if(typeid (int) == typeid (dbParam))
{
std::cout << "dbParam is int type" << "\tname = " << typeid (dbParam).name() << std::endl;
}
if(typeid (double) == typeid (iParam))
{
std::cout << "iParam is double type" << "\tname = " << typeid (iParam).name() << std::endl;
}
if(typeid (int) == typeid (iParam))
{
std::cout << "iParam is int type" << "\tname = " << typeid (iParam).name() << std::endl;
}
//----------------------------------------------------------------------
if(typeid (Base).before(typeid (SubOne)))
{
std::cout << "SubOne after Base" << std::endl;
}
else
{
std::cout << "SubOne before Base" << std::endl;
}
//----------------------------------------------------------------------
if(typeid (Base) == typeid (*pBase))
{
std::cout << "*pBase is Base type" << "\tname = " << typeid (*pBase).name() << std::endl;
}
if(typeid (SubOne) == typeid (*pBase))
{
std::cout << "*pBase is SubOne type" << "\tname = " << typeid (*pBase).name() << std::endl;
}
if(typeid (Base*) == typeid (pBase))
{
std::cout << "pBase is Base* type" << "\tname = " << typeid (pBase).name() << std::endl;
}
if(typeid (SubOne*) == typeid (pBase))
{
std::cout << "pBase is SubOne* type" << "\tname = " << typeid (pBase).name() << std::endl;
}
//----------------------------------------------------------------------
if(typeid (Base) == typeid (*pSub))
{
std::cout << "*pSub is Base type" << "\tname = " << typeid (*pSub).name() << std::endl;
}
if(typeid (SubOne) == typeid (*pSub))
{
std::cout << "*pSub is SubOne type" << "\tname = " << typeid (*pSub).name() << std::endl;
}
if(typeid (Base*) == typeid (pSub))
{
std::cout << "pSub is Base* type" << "\tname = " << typeid (pSub).name() << std::endl;
}
if(typeid (SubOne*) == typeid (pSub))
{
std::cout << "pSub is SubOne* type" << "\tname = " << typeid (pSub).name() << std::endl;
}
//----------------------------------------------------------------------
if(typeid (Base) == typeid (*pSub2))
{
std::cout << "*pSub2 is Base type" << "\tname = " << typeid (*pSub2).name() << std::endl;
}
if(typeid (SubOne) == typeid (*pSub2))
{
std::cout << "*pSub2 is SubOne type" << "\tname = " << typeid (*pSub2).name() << std::endl;
}
if(typeid (Base*) == typeid (pSub2))
{
std::cout << "pSub2 is Base* type" << "\tname = " << typeid (pSub2).name() << std::endl;
}
if(typeid (SubOne*) == typeid (pSub2))
{
std::cout << "pSub2 is SubOne* type" << "\tname = " << typeid (pSub2).name()<< std::endl;
}
//----------------------------------------------------------------------
if(typeid (Base*) == typeid (pNull))
{
std::cout << "pNull is Base* type" << "\tname = " << typeid (pNull).name() << std::endl;
}
if(typeid (SubOne*) == typeid (pNull))
{
std::cout << "pNull is SubOne* type" << "\tname = " << typeid (pNull).name() << std::endl;
}
return 0;
}
运行结果: