第66课.c++中的类型识别
1.类型识别
静态类型:变量(对象)自身的类型
动态类型:指针(引用)所指向的对象的实际类型
2.问题:
void test(Base* b)
{
/* 危险的转换方式
* 如b正好指向子类,则没有问题。如果b正好指向父类,则此处则有风险
*/
Derived* d = static_cast<Base*>b;
}
解决办法:
实际的判断下b指针究竟指向的是什么对象(父类还是子类);即如何得到对象的动态类型
方案一:利用多态
a.在基类中定义虚函数放回具体的类
b.所有的派生类都必须实现类型相关的虚函数
c.每个类中的类型虚函数都需要不同的实现
eg:
#include <iostream>
#include <string>
using namespace std;
class Base
{
public:
virtual string type()
{
return "Base";
}
};
class Derived : public Base
{
public:
string type()
{
return "Derived";
}
void printf()
{
cout << "I'm a Derived." << endl;
}
};
class Child : public Base
{
public:
string type()
{
return "Child";
}
};
void test(Base* b)
{
if(b->type() == "Derived")
{
Derived* d = static_cast<Derived*>(b);
d->printf();
}
}
int main()
{
Base b;
Derived d;
Child c;
cout << 1 << ": "<< endl;
test(&b);
cout << 2 << ": "<< endl;
test(&d);
cout << 3 << ": "<< endl;
test(&c);
return 0;
}
缺点:
a.必须从基类开始提供类型虚函数
b.所有的派生类都必须重写类型虚函数
c.每个派生类的类型名必须唯一
方案二:
c++中提供了typeid关键字用于获取类型信息(头文件typeinfo)
a.type关键字返回对应参数的类型信息
b.typeid返回一个type_info类对象(数据存储在这里面)
c.当typeid的参数为NULL时将抛出异常
typeid的关键字的使用
int i = 0;
const type_info& tiv = typeid(i); // 没有虚函数表,返回静态类型
const type_info& tii = typeid(int); // 返回静态类型
cout << (tiv = tii) << endl;
typeid的注意事项
a.当参数为类型时:放回静态类型信息
b.当参数为变量时:
1).不存在虚函数表:返回静态类型信息
2).存在虚函数表: 返回动态类型信息
eg:
#include <iostream>
#include <string>
#include <typeinfo>
using namespace std;
class Base
{
public:
virtual ~Base()
{
}
};
class Derived : public Base
{
public:
void printf()
{
cout << "I'm a Derived." << endl;
}
};
void test(Base* b) // 当b对象中没有虚函数表时,打印静态类型(Base)
{
const type_info& tb = typeid(b);
cout << tb.name() << endl; // 打印类型名
}
int main(int argc, char** argv)
{
int i = 0;
const type_info& tiv = typeid(i);
const type_info& tii = typeid(int);
cout << (tiv == tii) << endl;
Base b;
Derived d;
test(&b); // 对象中存在虚函数表
test(&d); // 子类对象中继承了父类中的虚函数表
return 0;
}