每日C++_1117

RTTI:(Run Time Type Identification) 运行时类型识别


通过运行时类型识别,程序能够使用基类的阵阵或者引用来检查这些指针或者引用所指对象的实际派生类型
1 dynamic_cast 能够将基类的指针或者引用安全的转换为派生类的指针或者引用
2 typeid 返回指针或者引用所指对象的实际类型;
以上方法,要求基类必须有虚函数
因为只有虚函数的存在,这两个运算符才会使用指针或者引用所绑定的对象的动态类型(new的类型)
强制转换 Human *p = new Men;
    Men *p2 = (Men*)(p);//c风格强转
    
    Men *p3 = dynamic_cast<Men*>(p);
    if(p3!=nullptr)
        cout<<"success"<<endl;

2:typeid(类型[指针/引用]) 也可以 typeid(表达式)


拿到对象类型信息,返回一个常量对象的引用
两个指针定义的类型相同(Human),不管new的啥,typeid都相同
Human *A=new xxx; Human *B=new xxx;
typeid(A)==typeid(B)    
比较实际指向,应该这么写
Human *A=new xxx; Human *B=new xxx2;
typeid(*A)==typeid(*B)    
实际这样也成立
Human *A=new xxx;
typeid(*A) == typeid(xxx);

type_info :


1, .name 返回一个类名
Human *A=new xxx;
const type_info & tp = typeid(*A);
cout<<tp.name()<<endl;

注意:要求基类必须有虚函数

final:
加在类名后,则不能作为基类

静态类型与动态类型
静态:变量声明时的类型,编译的时候是已知的
动态:指的是指针/引用,所代表内存中对象的类型,在运行的时候知道。
以上只有在基类指针/引用,才存在这种静态类型和动态类型不一致的情况。

左值和右值


左值:能用在赋值语句等号左侧的东西,他能代表一个地址
右值:不能作为左值就是右值
(a=4)=8; //整个赋值语句的结果仍为左值
int a = 1;//变量为左值
string ac = "xxx";//string vector 容器下标需要左值
引用分类
左值引用:绑定左值 int a = 10; int &ccc = a;
const 引用 : const int &sss =  a;
右值引用:(new!)
    int && ref =3;//3为临时变量,绑定到一个常量
    ref = 5;
左值引用;
int a = 1; int &b{a}; 左值引用必须要绑定到左值
const 引用可以绑定到右值
const int &cccc= 1;

右值引用:必须绑定到右值的引用
希望用右值引用用来绑定一些即将销毁或者一些临时的对象上。
int && ref =3;//理解为一个对象名或整形名
const引用不仅可以绑定左值,也可以绑定右值
总结:返回非引用类型的函数,连同算术关系,位以及后置递增运算符,都生成右值

++i 左值表达式,先加后用, i+1,返回自身
i++ 右值,先用后加
    int i = 1;
    ++i = 100;

    int&& ce = i++;
    int& ce2 = ++i;
总结2:
所有变量,看成左值,因为是有地址,右值绑不上
函数里所有形参都是左值,int fun(int i,int &&w) w为右值引用,但是w本身是左值
临时变量都是右值

右值引用的目的:


提高程序运行效率,把拷贝对象变成移动对象来提高程序运行效率
应付移动构造函数,应付移动复制运算符用的

move 把一个左值强制转换为一个右值
    int i = 10;
    int&& dd = std::move(i);

    i = 100;


练习如下

 

Guess you like

Origin blog.csdn.net/qq_35337794/article/details/121384918