C++中的类型转换与类型识别 2
来源:互联网 发布:amx105突击型数据 编辑:程序博客网 时间:2024/06/03 10:30
C++ 基础内容, 不值一提
Author:Jacky Wu
引用该文章,须注明其出处 http://blog.csdn.net/imwkj
3:多态中的类型转换
多态中的类型转换是通过使用基类的指针或者引用来实现的,包括“向上类型转换(upcasting)”和“向下类型转换(downcasting)”,其中向下类型转换的实现是通过virtual 机制实现的,关于C++ 中virtual机制要好好理解,这里仅仅聊聊它们之中的类型转换。
a.向上类型转换 upcasting
//Inheritance & upcasting
enum note { middleC, Csharp, Eflat };
class Instrument {
public:
void play(note) const {
cout << "Instrument::play" << endl;
}
};
class Wind : public Instrument {
public:
void play(note) const {
cout << "Wind::play" << endl;
}
};
void tune(Instrument& i) {
//这里可能发生类型转换
i.play(middleC);
}
int main() {
Wind flute;
tune(flute); //传递的是Wind型对象,发生向上类型转换
}
//输出结果:
Instrument::play
在这里由于自动发生了类型转换,Wind 类型被自动转换到Instrument基类型上(只有显示继承关系才能发生这种转换),在这种情况下,显然程序输出的结果不是我们所期望的,如果想发生正确的调用就必须使用虚机制(virtual class& function)。在这里,我们只谈类型转换。我们先来看一下发生正确调用的类型转换:
//Inheritance & upcasting
enum note { middleC, Csharp, Eflat };
class Instrument {
public:
virtual void play(note) const { //只是在这里声明为虚函数
cout << "Instrument::play" << endl;
}
};
class Wind : public Instrument {
public:
void play(note) const {
cout << "Wind::play" << endl;
}
};
void tune(Instrument& i) {
//这里可能发生类型转换
i.play(middleC);
}
int main() {
Wind flute;
tune(flute); //传递的是Wind型对象,发生向上类型转换
}
输出结果:
Wind::play
这才是正确的“向上类型转换”,关于类的虚机制,我们在后面专门介绍。
b.向下类型转换(downcasting)
由于向上类型转换是安全的转换,在转换过程中会变成更一般的基类型,所以在转换后,一般不会出现错误。但向下类型转换就会出现迷惑,由一般基类型转换到子类型就会出现不清楚的问题。举个例子,Pet (宠物) 代表一个类型,Cat 和 Dog是它的派生子类,从Cat,或者Dog转换到Pet,是可以理解并正确的,但是如果是一个Pet,那如何知道它是必须转换成Cat还是Dog??这必须使用C++中的RTTI(run-time type identification) 运行时刻类型识别机制来进行处理。
有几个关键字要用到,他们是typeid , static_cast , dynamic_cast,为了能够安全的进行 downcasting,我们就得学会使用这些关键字,但是更好的方法是使用C++提供的虚机制。
由于C++在考虑到了效率因素,它在类的实现中并没有给每个类额外的加上“类型信息” (class information) ,所以我们就不能直接对普通类进行转换,因此,在使用这个功能的时候,类必须是多态方式实现的(必须有virtual机制),看代码:
class Pet {
public:
virtual ~Pet() {}
};
class Dog : public Pet {};
class Cat: public Pet {};
int main() {
Pet* pt = new Cat; //Upcast
//尝试 将 pt转换为 Dog,这中转换是错误的,dg = 0
Dog* dg = dynamic_cast<Dog*> (pt);
//尝试转换为Cat,正确
Cat* ct = dynamic_cast<Cat*> (pt);
cout << " dg = " << dg << endl;
cout << " ct = " << ct << endl;
}
输出结果:
dg = 0
ct = 0x3d2480
可见,如果发生成功的dynamic_cast转换,返回得到的对象的地址,相反,失败的转换返回0,在这种情况下,我们必须对返回的结果做出判定,否则就可能会发生错误。
这样,程序会花费额外的开销,如果我们知道被转换的对象是何种类型,我们就可以使用static_cast,同时使用typeid来确保这种转换是正确的,看下面的代码:
#include <iostream>
#include <typeinfo>
using namespace std;
class Pet {
public:
virtual ~Pet() {}
};
class Dog : public Pet {};
class Cat: public Pet {};
int main() {
Dog adog;
Pet* apet = &adog; //正确的向上类型转换
Dog* dg = 0;
Cat* ct = 0;
cout << typeid(apet).name()<< endl;
cout << typeid(dg).name() << endl;
cout << typeid(ct).name() << endl;
//上面的输出结果和编译器相关
if(typeid(apet) == typeid(dg)) {//利用typeid()确定其所属类型
dg = static_cast<Dog*>(apet);
}
if(typeid(apet) == typeid(ct)) {
ct = static_cast<Cat*>(apet);
}
if(dg != 0) {
cout << "It is a Dog/n";
}
if(ct != 0) {
cout << "It is a Cat/n";
}
}
输出结果:
P3Pet
P3Dog
P3Cat
在这个程序中用了头文件<typeinfo> ,这是C++为RTTI提供支持的一个头文件。用typeid操作符来确定对象指针的所属类型,它返回的是一个指向静态type_info型对象的引用。由于static_cast , dynamic_cast不能转换到其他外部类型,所以这种转换是安全的,但是有一定的效率损失,在一般情况下我们使用dynamic_cast而不用static_cast。
C++中的类型转换由于牵涉到虚机制和RTTI机制,看起来会让人感到迷惑,同时有些复杂,如果弄清楚这两个重要的内在机制在理解类型转换就会很容易。
- C++中的类型转换与类型识别 2
- C++中的类型转换与类型识别 1
- c语言中的类型转换与复合类型
- c语言中的类型转换与复合类型
- C#.NET 中的类型转换
- C#.NET 中的类型转换
- C#.NET 中的类型转换
- C#.NET 中的类型转换
- C#.NET 中的类型转换
- C#.NET 中的类型转换
- C#.NET 中的类型转换
- C#.NET中的类型转换
- c语言中的类型转换
- C#.NET 中的类型转换
- C#.NET 中的类型转换
- C#.NET 中的类型转换
- C#.NET 中的类型转换
- C#.NET 中的类型转换
- MD5之C语言源代码
- 美化你的菜单
- 个人职业生涯规划发展的一些图
- datagrid 设定列宽
- 从数据库中读数据建立菜单
- C++中的类型转换与类型识别 2
- 今天不错哦!
- c++中const的作用- -
- 什么是BPM
- BPM业务流程管理的关键功能
- Writing a Winsock 2 Layered Service Provider(LSP) 译文(zz)
- 信息部门人员角色划分及任职资格
- IRC聊天工具常用命令(小卡片)
- Delphi开发中Windows API函数的应用