博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(C/C++学习笔记) 二十三. 运行时类型识别
阅读量:5217 次
发布时间:2019-06-14

本文共 3337 字,大约阅读时间需要 11 分钟。

二十三. 运行时类型识别

● 定义

运行时类型识别(Run-time Type Identification, RTTI)

通过RTTI, 程序能够使用基类的指针或引用来检查(check)这些指针或引用所指对象的实际派生类型.

 

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

typeid操作符, 返回指针或引用所指对象的实际类型;

dynamic_cast操作符, 将基类类型的指针或引用安全地转换为派生类型的指针或引用.

 

● 基类指针访问子类的特有成员函数

#include <iostream>

using namespace std;

 

class Base

{

public:

    virtual char* GetName()=0;

};

 

class Bint:public Base

{

public:

    char * GetName() {

return "Bint";}

    int GetInt() {

return 1;}

};

 

class BString:public Base

{

public:

    char* GetName() {

return "BString";}

    char* GetString() {

return "Hello";}

};

 

int main(int argc, char* argv[])

{

    Base* B1 = new Bint();    //也可以写成Base* B1 = (Base*)new Bint(); 但这里的(Base*)其实是多余的

    printf(B1->GetName());

    printf("\n");

    Bint *B2= static_cast<Bint*>(B1);    //下面要用基类指针B1来访问子类Bint的特有方法GetInt(), 我们首先要将B1静态转换为Bint

    if(B2)

        printf("%d", B2->GetInt());

    printf("\n");

    Base * C1 = new BString();

    printf(C1->GetName());

    printf("\n");

    BString *C2 = static_cast<BString *>(C1);

    if(C2)

        printf(C2->GetString());

    printf("\n");

    return 0;

}

 

 

RTTI与虚继承

如果使用了虚继承, 将子类对象的地址赋值给基类指针, 此时, 基类指针仍可识别为它所指的子类对象的实际类型.

RTTI (Runtime Type Identification) 运行时类型识别

typeid 是一个用于运行时类型识别的操作符, 它返回的是type_info类型的常引用, type_infoC++标准库的一个类.

使用typeid注意使用头文件typeinfo.h

#include <iostream>

#include <typeinfo>

 

using namespace std;

 

class Animal

{

public:

    virtual void display(){}

};

 

class Cow:public Animal{};

 

class Dog:public Animal {};

 

int main(){

    Animal *anm;

    Cow cw;

    Dog dg;

 

    cout << "type of anm is : "<<typeid(anm).name()<<endl;

    cout << "type of cw is : "<<typeid(cw).name()<<endl;

    cout << "type of dg is : "<<typeid(dg ).name()<<endl;

 

    // initializing base pointer with the address of a derived class object;

    anm = &cw;

    cout<<"type of *anm when pointing to cw is: "<<typeid(*anm).name()<<endl;

    anm = &dg;

    cout<<"type of *anm when pointing to dg is: "<<typeid(*anm).name()<<endl;

    system("PAUSE");

    return 0;

}

 

● 标准C++的类型转换符

对于强制类型转换的风险, 最好的解决方法就是不要使用C风格的强制类型转换,而是使用标准C++的类型转换符:static_castdynamic_castreinterpret_cast、和const_cast

用法:

dynamic_cast < typeid > ( expression ); 以此类推

※ 所有的cast操作符都是针对 指针或引用 来转换的,不能对普通类型进行操作.

static_cast

进行上行转换(把子类的指针或引用转换成基类表示)是安全的;进行下行转换(把基类指针或引用转换成子类表示)时,由于没有动态类型检查(check),所以是不安全的。

 

dynamic_cast

进行上行转换时,dynamic_caststatic_cast的效果是一样的;在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全

 

reinterpret_cast

将某一类型转换为原来的类型

#include "iostream.h"

 

int main(int argc, char* argv[])

{

    int n = 97;

    char p[4] = {0};

    p[0] = (char)n;    //将整型的n强转为字符型, 并作为数组p的第0个元素

    cout<<p<<endl;

    int *f = reinterpret_cast<int*>(&p);    //p(代表了数组p的第0个元素)的地址转换成原来的整型指针

    cout<<*f<<endl;

    return 0;

}

 

const_cast

强制将一个const变量(只读变量)变成一个非const等价形式(即并不就是把某个const变量转换为一般的变量)

#include <iostream>

using namespace std;

 

int main(int argc, char* argv[])

{

    const int a=1;

    int* b=const_cast<int*>(&a);    //不能是int b=const_cast<int>(a)

    * b=2; //const变量a的等价形式是*b

    cout<<* b<<endl;

}

 

● 数组和向量

在计算机领域, 一维数组(single-dimensional array)=向量(能自己管理内存,又不限长度); 二维数组(2-dimensional array)=矩阵

※"之所以选择'vector'这个名字,是因为Alex Stepanov作为C++标准库的设计者当初在寻找一个可以与内置数组类型区分开来的名字的时候,使用了"向量"这个表示; 他现在承认这确实是个错误,因为数学家们通常使用"向量"来表示一个定长的序列。

 

● 向量

向量的定义方式有四种:

vector<int> a(10);

vector<int> b(10, 1);

vector<int> c(b);

vector<int> d(b.begin(), b.begin()+3);

如果要输出向量中的所有元素, 可以有两种循环控制方式:

//第一种:

for (int i=0; i<a.size(); i++)

    cout<<a[i]<<" ";

//第二种:

for (vector<int>::iterator it=a.begin(); it!=a.end(); ++it)

    cout<<*it<<" ";

 

转载于:https://www.cnblogs.com/ArrozZhu/p/8378195.html

你可能感兴趣的文章
[置顶] Linux终端中使用上一命令减少键盘输入
查看>>
poj1422_有向图最小路径覆盖数
查看>>
BootScrap
查看>>
[大牛翻译系列]Hadoop(16)MapReduce 性能调优:优化数据序列化
查看>>
WEB_点击一百万次
查看>>
CodeForces - 878A Short Program(位运算)
查看>>
路冉的JavaScript学习笔记-2015年1月23日
查看>>
Mysql出现(10061)错误提示的暴力解决办法
查看>>
2018-2019-2 网络对抗技术 20165202 Exp3 免杀原理与实践
查看>>
NPM慢怎么办 - nrm切换资源镜像
查看>>
CoreData 从入门到精通(四)并发操作
查看>>
Swift - UIView的常用属性和常用方法总结
查看>>
Swift - 异步加载各网站的favicon图标,并在单元格中显示
查看>>
Java编程思想总结笔记Chapter 5
查看>>
[LeetCode]662. Maximum Width of Binary Tree判断树的宽度
查看>>
WinForm聊天室
查看>>
【Python学习笔记】1.基础知识
查看>>
梦断代码阅读笔记02
查看>>
selenium学习中遇到的问题
查看>>
大数据学习之一——了解简单概念
查看>>