近来学习Java逐渐引发了一些对C++相关属性的思考。之前搞清楚了基于虚函数的C++的类Java的多态的实现。今天又想起Java里面的instanceof关键字在C++里面的实现,综合了一些相关的资料,发现还是可行的。instanceof是一种运行态的操作,C++作为一个编译型语言默认是没有在编译过程中获得运行态的状态的,所以要想获得这种扩展的支持需要激活C++的RTTI(Run-Time Type Identification)支持。
首先,打开编译器支持:
VC - Project - Setting - C++ - Category: C++ Language - Enable Run-Time Type Infomation
然后隆重介绍两个关键字
typeid dynamic_cast
类似Java语言的多态和instanceof正是由RTTI借助这两个关键字来实现的。
class weapon
{
.........
}
class gun : public weapon
{
public:
gun() {}
virtual ~gun() {}
virtual shoot() =0;
};
class pistol : public gun
{
pistol() {}
virtual ~pistol() {}
virtual shoot() {cout << "pistol" << endl;}
}
class shootgun : public gun
{
..............
}
类的向上转化:(Java中的安全转化)
gun * pg = static_cast<pg*>(new pistol()); //显式的向上转化是逻辑安全的,所以使用static_cast替代dynamic_cast以提高速度。
类的向下转化:(Java中的Instanceof)
void func(gun * pg)
{
if(typeid(*pg) == typeid(shootgun))
{
cout << "shootgun" << endl;
}
else if(typeid(*pg) == typeid(pistol))
{
cout << "pistol" << endl;
}
}
此时即便指针类型是gun*, 也可以向下确认到pistol的子类型。并进而使用dynamic_cast将父类的指针向下转化为具体的子类。并调用子类独有的函数。
pistol pp = dynamic_cast<pistol*>(pg);
pp->xxxx;
程序到现在为止表现的很完美,类的指针向下转化为具体的子类。但是instanceof的作用不止于此,在做类行判断时,对象所属类的超类也应该符合instanceof的条件,而我们在func里面增加判断:
if(typeid(*pg) == typeid(gun))
和
if(typeid(*pg) == typeid(weapon))
则会发现判断条件不成功,所以typeid只能精确表示当前类,却不具有判断超类的能力。
修改程序如下:
void func(gun* pg)
{
weapon pw = dynamic_cast<weapon*>(pg)
if(pw != NULL)
{
cout << "pg is the instance of weapon" << endl;
}
gun *pgg = dynamic_cast<pistol*>(pg)
if(pgg!= NULL)
{
cout << "pg is the instance of gun" << endl;
}
pistol pp = dynamic_cast<pistol*>(pg)
if(pp != NULL)
{
cout << "pg is the instance of pistol" << endl;
}
shootgun ps = dynamic_cast<shootgun*>(pg);
if(ps != NULL)
{
cout << "pg is the instance of shootgun" << endl;
}
}
当输入pistol的指针后,就会发现pistol的所有超类和本类都满足判断:weapon gun pistol
结合以上所有,我们实现一个基于RTTI的instanceof
#define instanceof(pobj,cls) (dynamic_cast<cls>(pobj) != NULL)