第66课.c++中的类型识别

1.类型识别

静态类型:变量(对象)自身的类型
动态类型:指针(引用)所指向的对象的实际类型

2.问题:

void test(Base* b)
{
/* 危险的转换方式
* 如b正好指向子类,则没有问题。如果b正好指向父类,则此处则有风险
/
Derived
d = static_cast<Base*>b;
}

解决办法:

 实际的判断下b指针究竟指向的是什么对象(父类还是子类);即如何得到对象的动态类型

方案一:利用多态

a.在基类中定义虚函数放回具体的类
b.所有的派生类都必须实现类型相关的虚函数
c.每个类中的类型虚函数都需要不同的实现

eg:

include

include

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

include

include

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;
}

注意:typeid得到的类型名在不同的编译器下面是不同的

posted @ 2019-12-13 16:27  人民广场的二道贩子  阅读(200)  评论(0)    收藏  举报