您的位置:首页 > 编程语言 > C语言/C++

第六十六课、c++中的类型识别

2017-02-09 22:14 225 查看
一、类型识别

1、在面向对象中可能出现下面的问题

(1)、基类指针指向子类对象

(2)、基类引用成为子类对象的别名



A、静态类型: 变量(对象)自身的类型(期望的、确定的类型)

B、动态类型: 指针(引用)所指向实际对象的类型





2、解决方案

(1)、在类中定义虚函数返回具体类型的信息

(2)、所有的派生类都必须实现类型相关的虚函数

(3)、每个类中的虚函数都需要不同的实现

#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 print()
{
cout << "I'm a Derived." << endl;
}
};

class Child : public Base
{
public:
string type()
{
return "Child";
}
};

void test(Base* b)
{
//危险的转换方式。因为b可能实际类型可能不是Derived的类型
//Derived* d = static_cast<Derived*>(b);

if(b->type() == "Derived")
{
Derived* d = static_cast<Derived*>(b);
d->print();
}
//如果类中没有虚函数表,则调用dynamic_cast会直接报错,编译不过。
//当父、子类没有继承关系时,dynamic_cast返回false,否则会转换后
//实际对象的地址
cout <<  dynamic_cast<Derived*>(b) << endl;
}

int main()
{
Base b;
Derived d;
Child c;

test(&b); //Base与Base没有继承关系,dynamic_cast返回false
test(&d);  //Derived与Base有继承关系,dynamic_cast转换后对象的地址
test(&c);  //Child与Derived没有继承关系,返回false

return 0;
}
/*输出结果:
0
I'm a Derived.
0x23feb8
0
*/


3、多态解决方案的缺陷

(1)、必须从基类开始提供类型虚函数

(2)、所有的派生类都必须重写类型虚函数

(3)、每个派生类的类型名必须不唯一

二、类型识别关键字

1、c++提供了typeid关键字用于获取类型信息

(1)、typeid关键字返回对应参数的类型信息

(2)、typeid返回一个type_info类对象

(3)、当typeid的参数为NULL时将抛出异常

(4)typeid关键字的使用



2、typeid的注意事项

(1)、typeid关键字在不同编译器下对类型名的处理可能不同

(2)、当参数为类型时(如int),返回静态类型信息

(3)、当参数为变量时(如 i)

A、不存在虚函数表:返回静态类型信息

B、存在虚函数表:返回动态类型信息

#include <iostream>
#include <string>
#include <typeinfo> //for typeid

using namespace std;

class Base
{
public:
virtual ~Base(){}
};

class Derived : public Base
{
public:
void print()
{
cout << "I'm a Derived." << endl;
}
};

void test(Base* b)
{
//const type_info& tb = typeid(b); //判断b的类型,Base*或Derived*
const type_info& tb = typeid(*b);  //判断对象的类型

cout << tb.name() << endl;
}

int main()
{
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);//无虚函数表数打印的类型名一样(因为Test参数为Base,即静态类型为Base),有虚函数表时则不一样

return 0;
}
/*输出结果:
1
4Base       //g++下类名前面的数字表示类名的长度
7Derived
*/


三、小结

(1)、c++中有动态类型和静态类型的概念

(2)、利用多态能够实现对象的动态类型识别

(3)、typeid是专用于类型识别的关键字

(4)、typeid能够返回对象的动态类型信息
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: