半小时掌握C++11之RIIT

102 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第12天,点击查看活动详情

type_info对象

C++提供了一个type_info类来获取对象类型信息:

  • 这个类的构造函数是private的,因此用户不能直接构造这样的对象,只能通过typeid()函数来获取这个对象.

  • 这个类对外提供了name(),operator==()等方法供用户使用.

  • typeid()可以对基本的数据类型和对象进行操作,这种情况下,是在编译期静态决定的

  • type_info也可以对类类型和类对象进行操作

    如果是声明了虚函数的类对象引用,则typeid()返回的是实际对象的类型信息,在运行时动态决定的;

    反之,则typeid()返回的是入参声明类型信息,在编译时静态决定的.

需要引入#include

基本数据类型和对象

typeid()可以对基本的数据类型和对象进行操作,这种情况下,是在编译期静态决定的

#include <iostream>
#include <typeinfo>
using namespace std;
​
int main()
{
   int a = 3;
   int b = 4;
   const std::type_info& tp3 = typeid(a);
   const std::type_info& tp4 = typeid(b);
   cout<<&tp3<<endl;
   cout<<&tp4<<endl;
   cout<<tp3.name()<<endl;
   cout<<tp4.name()<<endl;
   if(tp3==tp4){
      cout<<"yes!"<<endl;
   }
    return 0;  
}
/*
0x5613881a9d40
0x5613881a9d40
i
i
yes!
*/

虚函数的类对象

image-20221011133635228.png 虚函数指针房间的地址,找到抽屉柜

抽屉柜格子的上面有一个亚克力盒子,上面有了RT两个字母,这个盒子里放的是RTTI玻璃柜的地址

RTTI玻璃柜的前三层放的是贵重物品,上了锁,看不到,但是第四层是可以打开的

打开以后发现里面放着一个户型图礼盒的地址

走到这个地址去,把户型图打开,就可以看到户型的名字

#include <iostream>
using namespace std;
class Person //人
{
  public:
  virtual void fun()
   {
       cout << "全价票" << endl; //成人票全价
   }
};
class Student : public Person //学生
{
   public:
   virtual void fun() //子类完成对父类虚函数的重写
   {
       cout << "半价票" << endl;//学生票半价
   }
};
class Soldier : public Person{
   public:
   virtual void fun() 
   {
       cout << "军人票" << endl;
   }
};
​
int main()
{
   Person* p1 = new Student;
   long* p2 = (long*)p1;
   long* vp = (long*)(*p2);
   typedef void(*Func)(void);
   Func f = (Func)vp[0];
   f();
   long* vr = (long*)(*(vp-1));
   long* vr2 = vr + 3;
   long* vr3 = (long*)(*vr2);
​
   const type_info* preal = (const type_info*)vr3;
   cout<<preal->name()<<endl; 
   cout<<"-------------"<<endl;
   cout<<typeid(*p1).name()<<endl; 
}
/*
半价票
7Student
-------------
7Student
*/

long* p2 = (long*)p1; p2是大房子的地址

long* vp = (long* )(*p2); *p2是房子里唯一房间vtpr里住的人

f();证明虚函数表地址没拿错;

long* vr = (long* )(* (vp-1));找到RT亚克力盒子,vp-1是RT亚克力房子的地址;* (vp-1)就是把房子里的东西拿出来,拿出来的东西就是RTTI玻璃柜的地址

long* vr2 = vr + 3;//拿到玻璃柜第四个格子放置的地址vr2

long* vr3 = (long )( vr2);//把第四个格子里的东西拿出来,这个里面的东西就是户型盒的地址

要向得到正确的结果,父类必须要有虚函数。只有当父类含有虚函数时,编译器才会对typeid中的表达式进行求值,否则,typeid返回的是表达式参数定义时的类型(静态类型)

int main()
{
   Person* p1 = new Student;
   Person* p2 = new Soldier;
   cout<<typeid(p1).name()<<endl;
   cout<<typeid(p2).name()<<endl;
   cout<<typeid(*p1).name()<<endl;
   cout<<typeid(*p2).name()<<endl;
}
/*
P6Person
P6Person
7Student
7Soldier
*/

总结

没有虚函数表,RTTI就不复存在