运行时类型识别

1.RTTI

1)运行时类型识别RTTI(Run-Time Type Identification),它能够获取基类指针或引用所指向的对象的实际类型,在C++中,为了支持RTTI提供了两个运算符:typeid和dynamic_cast

2)

2.dynamic_cast

2.1概念

1)dynamic_cast运算符用于将基类的指针或引用安全地转换成派生类的指针或引用,这是安全的“向下转型”,至于“向上转型”,即派生类指针或引用转换为其基类指针或引用,本身就是安全的,尽管可以使用dynamic_cast进行转换,但这是没必要的, 普通的转换已经可以达到目的,毕竟使用dynamic_cast是有开销的

2)dynamic_cast使用形式:dynamic_cast<type*>(expression)

  dynamic_cast<type&>(expression)

  dynamic_cast<type&&>(expression)   //右值引用

其中type必须是一个类类型,并且通常具有虚函数,否则编译会报错

2.2实例

  对于“向下转型”有两种情况。一种是基类指针所指对象是派生类类型的,这种转换是安全的;另一种是基类指针所指对象为基类类型,在这种情况下dynamic_cast在运行时做检查,转换失败,抛出bad_cast异常,返回结果为0:

class Base {
public:
    Base() {};
    virtual void Show() { cout << "This is Base calss"; }
};

class Derived :public Base {
public:
    Derived() {};
    void Show() { cout << "This is Derived class"; }
};

int main()
{
    //第一种情况,转换成功
    Derived d;
    Base& base1 =d;
    Derived& der1 = dynamic_cast<Derived&>(base1);
    cout << "第一种情况:";
    der1.Show();
    cout << endl;

    //第二种情况
    Base b;
    Base &base2 = b;
    cout << "第二种情况:";
    try {
        Derived & der2 = dynamic_cast<Derived&>(base2);
    }
    catch (bad_cast)
    {
        cout << "转化失败,抛出bad_cast异常" << endl;
    }

    return 0;
}

3.typeid

3.1概念

1)typeid运算符用于返回表达式的类型

2)typeid使用形式:typeid(expression);

  如果表达式的类型是类且至少包含有一个虚函数,则typeid返回表达式的动态类型,需要在运行时计算;否则,typeid操作符返回表达式的静态类型,在编译时就可以计算

3)typeid运算符的返回值是type_info类的引用,ype_info类在头文件typeinfo中定义

4)type_info类提供了public虚析构函数,以使用户能够用其作为基类。它的默认构造函数和拷贝构造函数及赋值操作符都定义为private,所以不能定义或复制type_info类的对象,程序中创建type_info对象的唯一方法是使用typeid运算符

3.2实例

class Base {};
class Derived: public Base {};

int main()
{
    Base b, *pb;
    pb = NULL;
    Derived d;

    cout << typeid(int).name() << endl
         << typeid(unsigned).name() << endl
         << typeid(long).name() << endl
         << typeid(unsigned long).name() << endl
         << typeid(char).name() << endl
         << typeid(unsigned char).name() << endl
         << typeid(float).name() << endl
         << typeid(double).name() << endl
         << typeid(string).name() << endl
         << typeid(Base).name() << endl
         << typeid(b).name()<<endl
         << typeid(pb).name()<<endl
         << typeid(Derived).name() << endl
         << typeid(d).name()<<endl
         << typeid(type_info).name() << endl;

    return 0;
}

VS和GCC的结果:

class Base {};
class Derived : public Base {};

int main()
{
    Base b, *pb;
    pb = NULL;
    Derived d;
    Base* pb2 = new Derived;//向上转型是安全的
    Base& b2 = d;
    Base* pb3 = &d;
    cout << typeid(pb2).name() << endl//输出Base *
        << typeid(b2).name() << endl //输出Base,b2是一个类的引用,但这个类没有虚函数
        << typeid(pb3).name() << endl//输出Base *,pb3是一个指针
        << typeid(*pb3).name() << endl;//输出Base,*pb3是一个类,但这个类没有虚函数

    return 0;
}

现在对Base加上一个虚函数:

class Base {
public:
    virtual void f() {}
};
class Derived : public Base {};

int main()
{
    Base b, *pb;
    pb = NULL;
    Derived d;
    Base* pb2 = new Derived;//向上转型是安全的
    Base& b2 = d;
    Base* pb3 = &d;
    cout << typeid(pb2).name() << endl//输出Base *,pb2是一个指针,不是类对象
        << typeid(b2).name() << endl //输出Derived,b2是一个基类的引用,这个类有虚函数,返回动态类型
        << typeid(pb3).name() << endl//输出Base *,pb3是一个指针,不是类对象
        << typeid(*pb3).name() << endl;//输出Derived,*pb3是一个类对象,这个类有虚函数,返回动态类型

    return 0;
}

原文地址:https://www.cnblogs.com/Joezzz/p/10436459.html

时间: 2024-11-01 18:14:41

运行时类型识别的相关文章

C++ Primer 学习笔记_102_特殊工具与技术 --运行时类型识别[续]

特殊工具与技术 --运行时类型识别[续] 三.RTTI的使用 当比较两个派生类对象的时候,我们希望比较可能特定于派生类的数据成员.如果形参是基类引用,就只能比较基类中出现的成员,我们不能访问在派生类中但不在基类中出现的成员. 因此我们可以使用RTTI,在试图比较不同类型的对象时返回假(false). 我们将定义单个相等操作符.每个类定义一个虚函数 equal,该函数首先将操作数强制转换为正确的类型.如果转换成功,就进行真正的比较:如果转换失败,equal 操作就返回 false. 1.类层次 c

RTTI 运行时类型识别

RTTI   运行时类型识别 typeid  ------  dynamic_cast dynamic_cast 注意事项: 1.只能应用于指针和引用之间的转化 2.要转换的类型中必须包含虚函数 3.转换成功返回的是子类的地址,失败返回NULL typeid注意事项: 1.typeid返回一个type_info对象的引用 2.如果想通过基类获得派生类的数据类型,基类必须带有虚函数 3.只能获取对象的实际类型

C++杂记:运行时类型识别(RTTI)与动态类型转换原理

运行时类型识别(RTTI)的引入有三个作用: 配合typeid操作符的实现: 实现异常处理中catch的匹配过程: 实现动态类型转换dynamic_cast. 1. typeid操作符的实现 1.1. 静态类型的情形 C++中支持使用typeid关键字获取对象类型信息,它的返回值类型是const std::type_info&,例: #include <typeinfo> #include <cassert> struct B {} b, c; struct D : B {

Java基础之RTTI 运行时类型识别

运行时类型识别(RTTI, Run-Time Type Identification)是Java中非常有用的机制,在Java运行时,RTTI维护类的相关信息. 多态(polymorphism)是基于RTTI实现的.RTTI的功能主要是由Class类实现的. Class类 Class类是"类的类"(class of classes).如果说类是对象的抽象和集合的话,那么Class类就是对类的抽象和集合. 每一个Class类的对象代表一个其他的类.比如下面的程序中,Class类的对象c1代

MFC 六大机制 (2) RTTI(运行时类型识别)

RTTI(Runtime Type Identification,运行时类型识别) 程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型.MFC 早在编译器支持 RTTI 之前,就具有了这项能力.承接上一章,我们现在要在 Console 程序中将 RTTI 仿真出来.我希望我的类库具备 IsKindOf() 的能力,能够在执行器检查某个对象是否"属于某种类",并传回 TRUE 或 FALSE.为了更直观地查看结果,我在 IsKindOf() 中加入了输出,使其达到如

【转载】C/C++杂记:运行时类型识别(RTTI)与动态类型转换原理

原文:C/C++杂记:运行时类型识别(RTTI)与动态类型转换原理 运行时类型识别(RTTI)的引入有三个作用: 配合typeid操作符的实现: 实现异常处理中catch的匹配过程: 实现动态类型转换dynamic_cast. 1. typeid操作符的实现 1.1. 静态类型的情形 C++中支持使用typeid关键字获取对象类型信息,它的返回值类型是const std::type_info&,例: #include <typeinfo> #include <cassert>

RTTI(运行时类型识别)

运行时类型识别(Run-time type identification , RTTI),是指在只有一个指向基类的指针或引用时,确定所指对象的准确类型的操作.其常被说成是C++的四大扩展之一(其他三个为异常.模板和名字空间). 使用RTTI的两种方法: 1.typeid() 第一种就像sizeof(),它看上像一个函数,但实际上它是由编译器实现的.typeid()带有一个参数,它可以是一个对象引用或指针,返回全局typeinfo类的常量对象的一个引用.可以用运算符“= =”和“!=”来互相比较这

C/C++杂记:运行时类型识别(RTTI)与动态类型转换原理

运行时类型识别(RTTI)的引入有三个作用: 配合typeid操作符的实现: 实现异常处理中catch的匹配过程: 实现动态类型转换dynamic_cast. 1. typeid操作符的实现 1.1. 静态类型的情形 C++中支持使用typeid关键字获取对象类型信息,它的返回值类型是const std::type_info&,例: #include <typeinfo> #include <cassert> struct B {} b, c; struct D : B {

MFC中的运行时类型识别(RTTI)

RTTI是Runtime Type Identification的缩写,中文名为"运行时类型识别". MFC早在编译器支持RTTI之前,就有了这种能力.我们现在要以相同的手法,在Console程序中仿真出来.我希望我的类库具备IsKindOf 的能力,能在执行期侦测到某个对象是否属于某个类,并传回TRUE 或 FALSE.以形状 Shape为例 ,我希望: 即 长方形属于"长方形类",正方形属于"长方形类",圆不属于"长方形类"

C++ Primer 学习笔记_101_特殊工具与技术 --运行时类型识别

h2.western { font-family: "Liberation Sans",sans-serif; font-size: 16pt; }h2.cjk { font-family: "微软雅黑"; font-size: 16pt; }h2.ctl { font-family: "AR PL UMing CN"; font-size: 16pt; }h1 { margin-bottom: 0.21cm; }h1.western { fon