运行时类型识别
目标
在我们只有一个指向基类的指针或者引用时确定一个对象的准确类型,虚函数机制可以帮助我们确定类是哪种类型,但是却远远不够。例如下面的代码:
class shape()
{
shape();
~shape();
virtual void draw() = 0;
}
从这个基类派生出三种不同的类:circle、square、triangle。我们调用其中类的draw方法,即使用一个shape()的指针来调用,任然被正确调用。
注意:RTTI与异常一样,依赖驻留在虚函数表中的类型信息。如果试图在一个没有虚函数的类上用RTTI,就得不到预期的结果。(可以进行测试一下)
RTTI的两种使用方法
(1)使用typeid关键字,注意这是一个关键字,像sizeof一样。
(2)“安全类型向下映射”,其实就是与“向上映射”相反。实现的方法:创建一个函数来试着将 shape*指派为一个 circle* (在本例中 ),检查执行过程中的数据类型。如果这个函数返回一个地址,则成功;如果返回 NULL,说明我们并没有一个circle *对象。C++的RTII的“安全类型向下映射”就是按照这种“试探映射”函数的格式。例子:
shape *sp = new circle;
circle *cp = dynamic_cast<circle*>sp
if(cp) cout<<"cast successful"
见下面例子
class shape
{
protected:
static int count;
public:
shape()
{
count++;
}
virtual ~shape()
{
count--;
}
virtual void draw()
{
}
};
int shape::count = 0;
class rectage:public shape
{
void operator=(rectage &);
protected:
static int count;
public:
rectage()
{
count++;
}
~rectage()
{
count--;
}
void draw()
{
std::cout<<"~~~~~~"<<std::endl;
}
static int quatiy()
{
return count;
}
};
int rectage::count = 0;
class circle:public shape
{
void operator=(rectage &);
protected:
static int count;
public:
circle()
{
count++;
}
~circle()
{
count--;
}
void draw()
{
std::cout<<"~~~~~~"<<std::endl;
}
static int quatiy()
{
return count;
}
};
int circle::count = 0;
int main( int argc , char *argv[] )
{
std::vector<shape *> vVal;
time_t t;
srand((unsigned)time(&t));
const int mod = 12;
for ( int i = 0 ; i < rand()%12; ++i )
{
vVal.push_back((shape *)(new rectage));
}
for ( int j = 0; j < rand()%12; ++j )
{
vVal.push_back((shape *)(new circle));
}
int iRecCount = 0;
int iCirCount = 0;
for ( int u = 0; u < vVal.size() ; ++u)
{
if ( dynamic_cast<rectage*>(vVal.at(u)))
{
iRecCount++;
}
if ( dynamic_cast<circle*>(vVal.at(u)))
{
iCirCount++;
}
}
std::cout<<vVal.size()<<std::endl
<<iRecCount <<" == "<<rectage::quatiy()<<std::endl
<<iCirCount <<" == "<<circle::quatiy()<<"\n";
return EXIT_SUCCESS;
}
总结
RIIT是C++的第二大特征(第一大特征是什么额?),上面只是大概的介绍了一下它,详细的使用见下面分解。