我是靠谱客的博主 大气曲奇,最近开发中收集的这篇文章主要介绍typeid 与 dynamic_cast(C++学习),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

RTTI

Run-Time Type Information

运行时类型信息

Run-Time Type Identification

运行时类型识别

C++ 通过下面两个 操作符 提供RTTI功能

  • typeid

  • dynamic_cast

其中:

  • typeid 返回 type_info 类的对象的一个引用

  • typeid 会抛出 bad_typeid 的异常

  • dynamic_cast 会抛出 bad_cast 异常

这3个类在头文件 typeinfo 中:

namespace std{
class type_info;
class bad_cast;
class bad_typeid;
}

typeid 操作符

  • 操作符 typeid 用法上类似于操作符 sizeof (?)
  • 只有当 typeid 的参数是带虚函数的类类型的对象的时候,才返回动态类型信息.

    • 对其他,返回静态的、编译时的类型

例子:

#include <typeinfo>
#include <iostream>
#include <string>
#include <vector>
using std::cout;
using std::endl;

int func(int arg){return 0;}
typedef int (*func_ptr)(int arg);

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

int main()
{

int integer(1);

double real(1.0);

int array[10]={1,2,3};

int * array_header = array;

std::string string;

std::vector<int> int_vector;

func_ptr f = func;


cout<<"integer
: "<<typeid(integer).name()
<<endl;

cout<<"real
: "<<typeid(real).name()
<<endl;

cout<<"array[10]
: "<<typeid(array).name()
<<endl;

cout<<"array_header: "<<typeid(array_header).name()<<endl;

cout<<"std::string : "<<typeid(string).name()
<<endl;

cout<<"std::vector : "<<typeid(int_vector).name()
<<endl;

cout<<"function
: "<<typeid(func).name()
<<endl;

cout<<"function ptr: "<<typeid(f).name()
<<endl;

cout<<"custom class: "<<typeid(Base()).name()
<<endl;


cout<<std::endl;


cout<<"int
: "<<typeid(int).name()
<<endl;

cout<<"double
: "<<typeid(double).name()
<<endl;

cout<<"std::vector : "<<typeid(std::vector<int>).name()<<endl;

cout<<"Base
: "<<typeid(Base).name()
<<endl;

cout<<"Base*
: "<<typeid(Base*).name()
<<endl;

cout<<"Base&
: "<<typeid(Base&).name()
<<endl;


return 0;
}

结果:

 

g++

MSVC

integer

i

int

real

d

double

array[10]

A10_i

int [10]

array_header

Pi

int *

std::string

Ss

class std::basic_string<char,struct std::char_traits<char>
,class s td::allocator<char> >

std::vector

St6vectorIiSaIiEE

class std::vector<int,class std::allocator<int> > 

function

FiiE

int __cdecl(int)

function ptr

PFiiE

int (__cdecl*)(int)

custom class

F4BasevE

class Base __cdecl(void)

  

int

i

int

double

d

double

std::vector

St6vectorIiSaIiEE

class std::vector<int,class std::allocator<int> > 

Base

4Base

class Base

Base*

P4Base

class Base *

Base&

4Base

class Base

对于每个类型,返回一个唯一的字符串,但该字符串的具体内容,与编译器实现有关。

在 typeid 中:

  • 数组不会退化为指针,比如int array[10]
  • 函数不会退化为指针, func 和 f
  • 顶层cv-qualifiers会被忽略 typeid(D) == typeid(const D);
  • ...

dynamic_cast 操作符

#include <typeinfo>
#include <iostream>

class Base1 { public: virtual void func1(){} };
class Base2 { public: virtual void func2(){} };

class D:public Base1, public Base2 {};

int main()
{

Base1 * b1 = new D;

Base2 & b2 =
dynamic_cast<Base2&>(*b1);


std::cout << "Base1 " << uintptr_t(b1) <<" " << typeid(*b1).name() << std::endl

<< "Base2 " << uintptr_t(&b2) << " " <<typeid(b2).name() << std::endl;


return 0;
}

结果:

MSVC

g++

Base1 208960 class D
Base2 208964 class D

Base1 208088 1D
Base2 208092 1D

C++0x 5.2.7:

  • The result of the expression dynamic_cast<T>(v) is the result of converting the expression v to type T. T shall be a pointer or reference to a complete class type, or “pointer to cv void.”

dynamic_cast<T>(v) 中,T 是一个完整定义类的指针或引用,或者 void *。只能转换到 void *,不能从void*转换回来。

type_info 类

摘自 C++0x标准 18.7.1:

namespace std {

class type_info {

public:

virtual ~type_info();

bool operator==(const type_info& rhs) const;

bool operator!=(const type_info& rhs) const;

bool before(const type_info& rhs) const;

size_t hash_code() const throw();

const char* name() const;

type_info(const type_info& rhs) = delete; // cannot be copied

type_info& operator=(const type_info& rhs) = delete; // cannot be copied

};
}

这里面,我们目前最感兴趣的是成员函数: name()

bad_typeid 类

异常的定义(来自C++0x 18.7.3):

namespace std {

class bad_typeid : public exception {

public:

bad_typeid() throw();

bad_typeid(const bad_typeid&) throw();

bad_typeid& operator=(const bad_typeid&) throw();

virtual const char* what() const throw();

};
}

例子:

#include <iostream>
#include <typeinfo>

class Polymorphic {virtual void Member(){}};

int main ()
{

try {

Polymorphic * pb = 0;

std::cout << typeid(*pb).name();

} catch (std::bad_typeid& e) {

std::cerr << "bad_typeid caught: " << e.what() << std::endl;

}

return 0;
}

结果:

MSVC

bad_typeid caught: Attempted a typeid of NULL pointer!

g++

bad_typeid caught: std::bad_typeid

异常产生条件:

  • 多态
  • 空指针
  • 用*解引用

比如,如果pb定义改为

int * pb = 0;

或 typeid 行改为


std::cout << typeid(pb).name();

则不会有异常发生。

bad_cast 类

异常的定义(来自C++0x 18.7.2):

namespace std {

class bad_cast : public exception {

public:

bad_cast() throw();

bad_cast(const bad_cast&) throw();

bad_cast& operator=(const bad_cast&) throw();

virtual const char* what() const throw();

};
}

例子:

#include <iostream>
#include <typeinfo>

class Base {virtual void Member(){}};
class Derived : Base {};

int main ()
{

try {

Base b;

Derived& rd = dynamic_cast<Derived&>(b);

} catch (std::bad_cast& bc) {

std::cerr << "bad_cast caught: " << bc.what() << std::endl;

}

return 0;
}

结果:

MSVC

bad_cast caught: Bad dynamic_cast!

g++

bad_cast caught: std::bad_cast

  • 对指针cast失败,返回一个空指针
  • 对引用cast失败,则抛出bad_cast异常

参考

  • http://www.cplusplus.com/reference/std/typeinfo/bad_typeid

  • http://www.cplusplus.com/reference/std/typeinfo/bad_cast



FROM: http://blog.csdn.net/dbzhang800/article/details/6672591


最后

以上就是大气曲奇为你收集整理的typeid 与 dynamic_cast(C++学习)的全部内容,希望文章能够帮你解决typeid 与 dynamic_cast(C++学习)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(77)

评论列表共有 0 条评论

立即
投稿
返回
顶部