第66课 C++中的类型识别
1. 类型识别
(1)在面向对象中可能出现下面的情况
①基类指针指向子类对象
②基类引用成为子类对象的别名
▲静态类型——变量(对象)自身的类型(定义变量类型时类型或参数类型)
▲动态类型——指针(引用)所指向的对象的实际类型
(2)基类指针转子类指针:
①示例:Derived* d = static_cast<Derived*>(pBase); //危险的转换方式
②问题:不安全,是否能强制类型转换取决动态类型。
2. 利用多态获取动态类型
(1)解决方案
①在基类中定义虚函数,并返回具体的类型信息
②所有的派生类都必须实现类型相关的虚函数
③每个类中的类型虚函数都需要不同的实现
【编程实验】动态类型识别
- #include <iostream>
- #include <string>
- using namespace std;
- class Base
- {
- public:
- //在基类中提供个用来判断类型的虚函数
- //并且所有的派生类中都必须实现这个函数
- virtual string type()
- {
- return "Base"; //手动返回一个用于识别的标识符
- }
- };
- class Derived : public Base
- {
- public:
- string type()
- {
- return "Derived";
- }
- void print()
- {
- cout << "I'm a Derived." << endl;
- }
- };
- class Child : public Base
- {
- public:
- string type()
- {
- return "Child";
- }
- };
- void test(Base* b)
- {
- //危险的转换方式。因为b可能实际类型可能不是Derived的类型
- //Derived* d = static_cast<Derived*>(b);
- if(b->type() == "Derived")
- {
- Derived* d = static_cast<Derived*>(b);
- d->print();
- }
- //如果类中没有虚函数表,则调用dynamic_cast会直接报错,编译不过。
- //当父、子类没有继承关系时,dynamic_cast返回false,否则会转换后
- //实际对象的地址
- cout << dynamic_cast<Derived*>(b) << endl;
- }
- int main()
- {
- Base b;
- Derived d;
- Child c;
- test(&b); //Base与Base没有继承关系,dynamic_cast返回false
- test(&d); //Derived与Base有继承关系,dynamic_cast转换后对象的地址
- test(&c); //Child与Derived没有继承关系,返回false
- ;
- }
- /*输出结果:
- 0
- I'm a Derived.
- 0x23feb8
- 0
- */
(2)多态解决方案的缺陷
①必须从基类开始提供类型虚函数
②所有的派生类都必须重写类型虚函数
③每个派生类的类型名必须唯一
3. 类型识别关键字:typeid(须#include<typeinfo>)
(1)typeid关键字
①typeid关键字返回对应参数的类型信息
②typeid返回一个type_info类的对象
③当typeid的参数为NULL时抛出异常
(2)typeid关键字的使用
- ;
- const type_info& tiv = typeid(i); //得到变量i的类型信息
- const type_info& tii = typeid(int); //得到int类型信息
(3)typeid的注意事项
①当参数为类型时:返回静态类型信息
②当参数为变量时:
A.不存在虚函数表时:返回静态类型信息
B.存在虚函数表时:返回动态类型信息
【编程实验】typeid类型识别
- #include <iostream>
- #include <string>
- #include <typeinfo> //for typeid
- using namespace std;
- class Base
- {
- public:
- virtual ~Base(){}
- };
- class Derived : public Base
- {
- public:
- void print()
- {
- cout << "I'm a Derived." << endl;
- }
- };
- void test(Base* b)
- {
- //const type_info& tb = typeid(b); //判断b的类型,Base*或Derived*
- const type_info& tb = typeid(*b); //判断对象的类型
- cout << tb.name() << endl;
- }
- int main()
- {
- ;
- const type_info& tiv = typeid(i); //判断变量的类型
- const type_info& tii = typeid(int); //判断类的类型
- cout << (tiv == tii) << endl; //相等
- Base b;
- Derived d;
- test(&b);
- test(&d);
- ;
- }
- /*输出结果:
- 1
- 4Base //g++下类名前面的数字表示类名的长度
- 7Derived
- */
4. 小结
(1)C++中有静态类型和动态类型的概念
(2)利用多态能够实现对象的动态类型识别
(3)typeid是专用于类型识别的关键字
(4)typeid能够返回对象的动态类型信息
第66课 C++中的类型识别的更多相关文章
- JS中的类型识别
JS为弱类型语言,所以类型识别对JS而言尤为重要,JS中常用的类型识别方法有4种:typeof.Object.prototype.toString.constructor和instanceof. (1 ...
- C++中的类型识别
1,为什么会提出类型识别概念呢? 1,为什么在 C 语言中没有提出这个概念呢,就是因为在 C++ 中引入了面向对象的特性,面向对象里面有一个非常重要的原则就是赋值兼容性原则: 2,在面向对象中可能出现 ...
- 框架原理第二讲,RTTI,运行时类型识别.(以MFC框架讲解)
框架原理第二讲,RTTI,运行时类型识别.(以MFC框架讲解) 一丶什么是RTTI,以及RTTI怎么设计 通过第一讲,我们知道了怎么样升成一个窗口了,以及简单的消息循环. 第二讲则是主要讲解RTTI ...
- 关于js中的类型内容总结(类型识别)
JS 有7种数据类型: 6种原始类型:Boollean String Number Null Underfined Symbol 引用类型:Object 类型识别主要有以下四 ...
- C++之运行时类型识别RTTI
C++ Code 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 ...
- RTTI 运行时类型识别 及异常处理
RTTI 运行时类型识别 typeid ------ dynamic_cast dynamic_cast 注意事项: 1.只能应用于指针和引用之间的转化 2.要转换的类型中必须包含虚函数 3. ...
- RTTI (Run-Time Type Identification,通过运行时类型识别) 转
参考一: RTTI(Run-Time Type Identification,通过运行时类型识别)程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型. RTTI提供了以下两个 ...
- Scala 深入浅出实战经典 第49课 Scala中Variance代码实战(协变)
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- 数据库中字段类型对应的C#中的数据类型
数据库中字段类型对应C#中的数据类型: 数据库 C#程序 int int32 text string bigint int64 binary System.Byte[] ...
随机推荐
- sizzle源码分析 (3)sizzle 不能快速匹配时 选择器流程
如果快速匹配不成功,则会进入sizzle自己的解析顺序,主要流程如下: 总结流程如下: (1)函数sizzle是sizzle的入口,如果能querySelectAll快速匹配,则返回结果 (2)函数S ...
- 移动端图片滚动加载-lazyload实现的要点总结
最近在做移动端的营销页面时,遇到了页面有大量图片的情况,于是很自然的想到了要使用图片lazyload,PC端用着jQuery,也有现成的插件.但是在移动端,基本不用jQuery,于是就试着自己去造一下 ...
- Ridge Regression(岭回归)
Ridge Regression岭回归 数值计算方法的"稳定性"是指在计算过程中舍入误差是可以控制的. 对于有些矩阵,矩阵中某个元素的一个很小的变动,会引起最后计算结果误差很大,这 ...
- CVE: 2014-6271、CVE: 2014-7169 Bash Specially-crafted Environment Variables Code Injection Vulnerability Analysis
目录 . 漏洞的起因 . 漏洞原理分析 . 漏洞的影响范围 . 漏洞的利用场景 . 漏洞的POC.测试方法 . 漏洞的修复Patch情况 . 如何避免此类漏洞继续出现 1. 漏洞的起因 为了理解这个漏 ...
- Sharepoint学习笔记—习题系列--70-576习题解析 -(Q49-Q51)
Question 49You are designing a SharePoint 2010 intranet site for a corporation. Your design must mee ...
- iOS小型计算器
// // ViewController.m // 计算器 //屏幕的宽和高 #define SCREEN_W self.view.frame.size.width #define SCREEN_ ...
- Android Studio 2.2新功能预览
升级SDK可用Background 多加了个按钮,可用一边写代码一边下载SDK Instant Run 修改代码一秒启动 APK analyzer 分析任何的APK 查看APK下载包的大小,解压后的实 ...
- 【代码笔记】iOS-清除图片缓存UIActionSheet
一,效果图. 二,代码. RootViewController.m //点击任何处出现sheet -(void)touchesBegan:(NSSet *)touches withEvent:(UIE ...
- 【代码笔记】iOS-钢琴小游戏
一,效果图. 二,工程图. 三,代码. RootViewController.h #import <UIKit/UIKit.h> //加入头文件 #import <AudioTool ...
- 【工具相关】iOS-Reveal的使用
一,首先下载Reveal工具. Reveal的下载地址:http://revealapp.com/download. 下载界面如下图所示,选择Download Trail蓝色按钮可以进行下载: 二,新 ...