一、C++中类型识别ios
(1)在面向对象中可能出现下面的状况ide
@1:基类指针指向子类对象 Base *p = new child();函数
@2:基类引用成为子类对象的别名 Base& r = *p;spa
--上面的base是基类,child是这个基类的子类,第一种状况,因为赋值兼容性的存在,父类指针是能够指向子类对象的,可是咱们没法经过父类指针来知道当前指针指向的是不是子类对象。指针
--可是这时咱们能够说,指针p的静态类型是Base*(指针指望的类型),指针p的动态类型是child(由于这时指针p指向的类型不是自己指针p所指望的类型,因此child叫指针p的动态类型)对象
--第二种状况,Base&是r的静态类型,由于r这个引用指望获得的类型是Base这个父类,可是因为赋值兼容性原则,此时r成为了子类child所在堆空间的别名了,引用自己也没有办法肯定引用的到字符串
--底是父类对象仍是子类对象。因此child这个类型此时也是引用r的动态类型(由于和r自己想引用的类型不一样)。string
(2)静态类型:变量(对象)自己的类型叫作静态类型。it
(3)动态类型:指针(引用)所指向对象的实际类型。io
void test(Base *b)
{
child *d = static_cast<child*>(b); //危险的转换方式,若是b指针指向的子类对象,那就是彻底能够的。
}
基类指针是否能够强制类型转换为子类指针取决于动态类型。
二、C++中如何获得对象的动态类型?
(1)解决方案1:利用多态
@1:在基类中定义虚函数返回具体的类型信息(返回字符串,字符串来表示当前的类型信息)
@2:全部的派生类都必须实现类型相关的虚函数
@3:每一个类中的类型虚函数都须要不一样的实现
@4:咱们调用这个类对象的类型虚函数,就能够知道当前类到底是子类仍是父类了。
例:
#include <iostream>
#include <string>
using namespace std;
/*
* 利用多态的方法,进行对象的动态类型识别,也就是区别判断出,当前的父类指针指向的究竟是子类对象仍是父类对象。
*
*
*/
class Base
{
public:
virtual string type()
{
return "Base";
}
};
class child : public Base
{
public:
virtual string type() //子类重写这个函数,到时用来判断父类指针指向的究竟是父类对象仍是子类对象的
{
return "child";
}
void print()
{
cout << "I'm a child. " << endl;
}
};
void test(Base *b)
{
if ( b->type() == "child" )
{
child *c = static_cast<child*>(b);
c->print();
}
}
int main(void)
{
Base b;
child c;
test(&b);
test(&c);
return 0;
}
(2)多态解决方案的缺陷:
@1:必须从基类开始提供类型虚函数
@2:全部的派生类必须重写类型虚函数
@3:每一个派生类的名字必须惟一
(3)C++提供了typeid关键字用与获取类型信息,使用时要包含头文件<typeinfo>
@1:typeid关键字返回对应参数的类型信息
@2:typeid返回一个type_info类对象,因此要包含头文件typeinfo
@3:当typeid的参数为NULL时将抛出异常
(4)typeid关键字的使用
int i = 0;
const type_info& tiv = typeid(i);
const type_info& tii = typeid(int);
cout << (tiv == tii) << endl; // 1
(5)typeid的注意事项
@1:当参数为类型时:返回静态类型信息(指望的类型)
@2:当参数为变量时:
不存在虚函数表时:返回静态类型信息
存在虚函数表时:返回动态类型信息(实际对象的类型)
#include <iostream>
#include <string>
#include <typeinfo>
using namespace std;
/*
* 利用typeid,进行对象的动态类型识别,也就是区别判断出,当前的父类指针指向的究竟是子类对象仍是父类对象。
*
*
*/
class Base
{
public:
virtual ~Base()
{
}
};
class child : public Base
{
public:
};
void test(Base *b)
{
const type_info& tb = typeid(*b);
cout << tb.name() << endl;
}
int main(void)
{
int i = 0;
const type_info& tiv = typeid(i);
const type_info& tii = typeid(int);
cout << (tii == tiv) << endl;
Base b;
child c;
test(&b);
test(&c);
return 0;
}