阜阳市住房和城乡建设部网站,正能量网站不用下载直接进入,事件营销的步骤,wordpress编辑器代码C技能 runtime type identification(RTTI) 运行时类型识别在使用多态的时候经常用到。本文将会介绍RTTI的几个特征。1. 运行时类型转换下面的程序模仿了dynamic_casttype_id()类型转化符号#xff0c;根据每个类的id来判断当前的类型#xff0c;如果id不匹配#xf…C技能 runtime type identification(RTTI) 运行时类型识别在使用多态的时候经常用到。本文将会介绍RTTI的几个特征。1. 运行时类型转换下面的程序模仿了dynamic_casttype_id()类型转化符号根据每个类的id来判断当前的类型如果id不匹配则调用dynacast函数会转化失败#include iostream
#includevector
using namespace std;//base class
class Security{
protected:enum{BASEID 0};public:virtual ~Security(){}virtual bool isA(int id){return id BASEID;}
};///继承基类
class Stock : public Security{typedef Security Super;
protected:enum{ OFFSET 1, TYPEID BASEID OFFSET};
public:bool isA(int id){return id TYPEID || Super::isA(id);}//类型转换--通过检查id来判断基类的id 0,stock id 1,如果当前id stock id,则允许向下转换否则返回NULL static Stock* dynacast(Security* s){return (s-isA(TYPEID)) ? static_castStock*(s) : 0;}
};//继承了基类
class Bond : public Security{typedef Security Super;
protected:enum{ OFFSET 2, TYPEID BASEID OFFSET};
public:bool isA(int id){return id TYPEID || Super::isA(id);}static Bond* dynacast(Security* s){return (s-isA(TYPEID)) ? static_castBond*(s) : 0;}
};//继承了基类
class Investment : public Security{typedef Security Super;
protected:enum{ OFFSET 3, TYPEID BASEID OFFSET};
public:bool isA(int id){return id TYPEID || Super::isA(id);}static Investment* dynacast(Security* s){return (s-isA(TYPEID)) ? static_castInvestment*(s) : 0;}void special(){cout special Investment function\n;}
};//基类的孙子类
class Metal : public Investment{typedef Security Super;
protected:enum{ OFFSET 4, TYPEID BASEID OFFSET};
public:bool isA(int id){return id TYPEID || Super::isA(id);}static Metal* dynacast(Security* s){return (s-isA(TYPEID)) ? static_castMetal*(s) : 0;}
};int main(){vectorSecurity* portfolio;//基类指向派生类们 portfolio.push_back(new Metal);portfolio.push_back(new Investment);portfolio.push_back(new Bond); portfolio.push_back(new Stock);//for(vectorSecurity*::iterator it portfolio.begin(); it ! portfolio.end(); it){Investment* cm Investment::dynacast(*it);//指针转化if(cm)cm-special();elsecout not an Investment\n;} Security* sp new Metal;Investment* cp Investment::dynacast(sp);//根据多态理论调用对于的dynacast ,这里调用metal类的isAif(cp) cout its a Investment\n;Metal* mp Metal::dynacast(sp);//转化成功 if(mp) cout its a metal\n;//释放内存for(vectorSecurity*::iterator it portfolio.begin(); it ! portfolio.end(); it){delete *it;} return 0;
}上面是指针的转化如果使用dynamic_cast程序会简短很多#include iostream
#includevector
using namespace std;//base class
class Security{
public:virtual ~Security(){}
};///继承基类
class Stock : public Security{
};//继承了基类
class Bond : public Security{
};//继承了基类
class Investment : public Security{
public:void special(){cout special Investment function\n;}
};//基类的孙子类
class Metal : public Investment{
};int main(){vectorSecurity* portfolio;//基类指向派生类们 portfolio.push_back(new Metal);portfolio.push_back(new Investment);portfolio.push_back(new Bond); portfolio.push_back(new Stock);//for(vectorSecurity*::iterator it portfolio.begin(); it ! portfolio.end(); it){Investment* cm dynamic_castInvestment*(*it);//指针转化if(cm)cm-special();elsecout not an Investment\n;} Security* sp new Metal;//转化成功 Investment* cp dynamic_castInvestment*(sp);if(cp) cout its a Investment\n;Metal* mp dynamic_castMetal*(sp);//转化成功 if(mp) cout its a Metal\n;//释放内存for(vectorSecurity*::iterator it portfolio.begin(); it ! portfolio.end(); it){delete *it;} return 0;
}dynamic_cast要求多态还好这里的基类的析构是虚函数因此可以使用 dynamic_cast。另外dynamic_cast只能做指针或者引用的转化如果是普通的类型转化则无法用是否为空指针来判断这时可以用异常处理如果无法转化dynamic_cast会抛出异常。2.typedid操作符typeid可以获取对象运行时的信息他会返回一个type_info对象该对象记录了和这个对象有关的应用信息比如这个对象是多态的则它将会给出那个应用的大部分派生类信息否则就给出静态信息typeid操作符的一个用途是获得一个对象的动态类型的名称输出结果和编译器有关有的直接输出名字有的输出pk什么的p代表指针k代表const修饰符#include iostream
#includevector
#includetypeinfo
using namespace std;struct PolyBase{virtual ~PolyBase(){}
}; struct PolyDer : public PolyBase{PolyDer(){}
};struct NonPolyBase{
};struct NonPolyDer : public NonPolyBase{NonPolyDer(int){ }
};int main(){const PolyDer pd;const PolyBase* ppd pd;//父类指向子类cout typeid(ppd).name() endl;//输出父类自己的名字 cout typeid(*ppd).name() endl; //输出子类名称 cout boolalpha (typeid(*ppd) typeid(pd)) endl;//输出true const NonPolyDer npd(1);const NonPolyBase* nppd npd;cout typeid(nppd).name() endl;//输出父类 cout typeid(*nppd).name() endl; //输出父类 cout boolalpha (typeid(*nppd) typeid(npd)) endl;//false int i;cout typeid(i).name() endl; return 0;
}对于第一种含有虚函数和第二种不含有虚函数是完全不同的。因为typeid对多态敏感。使用指针的时候输出的是指针的静态类型当调用对象解析的时候则会输出动态类型而对于不含虚函数的类则不会有变化两次输出都是父类的名字typeid也支持内置的类型typeid不支持赋值操作也没用可供访问的构造函数3.继承体系的中间层次的转化比如有这么一个继承体系class B1{virtual ~B1(){}};class B2{virtual ~B2(){}};class MI : public B1, public B2{};class Mi2 : public MI{};那么创建一个Mi2对象可以转化为MI,B1,B2;#include iostream
using namespace std;class B1{public:virtual ~B1(){}
};class B2{public:virtual ~B2(){}
};class MI : public B1, public B2{};class Mi2 : public MI{};int main(){B2* b2 new Mi2;Mi2* pmi2 dynamic_castMi2*(b2);B1* b1 dynamic_castB1*(b2);MI* mi dynamic_castMI*(b2);return 0;
}4 void型指针不可以把void*和typeid和dynamic_cast联系起来5.虚基类类型向下转化当基类是虚基类的时候c不允许C语言的默认指针转化但是可以使用dynamic_cast;