IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++【对象模型】| 【09】类模板、异常处理及执行期类型识别 -> 正文阅读

[C++知识库]C++【对象模型】| 【09】类模板、异常处理及执行期类型识别

索引

C++【对象模型】| 【01】简单了解C++对象模型的布局
C++【对象模型】|【02】构造函数何时才会被编译器自动生成?
C++【对象模型】|【03】拷贝构造是如何工作的,何时才会用到呢?
C++【对象模型】 | 【04】程序在内部被编译器如何转化?
C++【对象模型】 | 【05】类与类之间各种关系下对数据成员的存取、绑定、布局
C++【对象模型】| 【07】构造、析构、拷贝做了哪些事?
C++【对象模型】| 【08】类在执行期会处理哪些事呢?
C++【对象模型】| 【09】类模板、异常处理及执行期类型识别

三种扩充性质将会影响C++对象:
template、exception handing、runtime type identification;

1、Template

Template:该模板表达式将在编译时期而非执行期被评估,将给程序带来重大的效率提升;
但同时也带来缺点,当与其像依赖的头文件,若产生修改将会重新编译;

1.1 emplate实例行为

【实例化】表示进程将真正的类型和表达式绑定到template相关形式参数上的操作;

当编译器看到templat class 声明时,会如何处理呢?

在实际程序中,它却没有反应;class中的每一个都只能通过该类模板的实例来调用;
template<float>::freeList;	// 可通过尖括号中不同类型创建出不同的实例

【指针却在不同类型下不会产生多个实例?】
- 由于指向一个类对象的指针本身不是一个类对象,故该指针不需要与对象相关的任何数据,故不用将其实例化,但C++标准禁止这样处理;

【上述为指针,那么引用呢?】
- 它将会被实例化,否则将会报错;

如何让成员函数需要使用的才进行实例化,编译器不会这样要求,需要使用者来主导,为什么呢?

- 空间上和时间上的考虑,如果类中有大量成员函数,但实际用到只有几个,那么将会耗费大量时间和空间;
- 尚未实现的机能,主要实例化真正用到的成员函数即可;
Point<float> *p = new Point<float>;
需要实例化的有:Point的float类型、new、默认构造三种;

【此类函数在何时将会被实例化呢】
- 如果在编译时,函数将实例化在Point原文件和p所在文件中;
- 如果在链接时,编译器会被重新激活,将template函数实例放在其他文件中;

于template内,什么样的编译器会在编译器处理template声明时被标示出来?

如cfront对template完全解析但不做类型检验,在每一个实例化操作发生时才做类型检验;

1.2 template中名称决议法

extern double foo(double);

template<class type>
class ScopeRules {
public:
	void invariant() {
		_member = foo(_val);	// foo不是取决于模板参数
	}	
	type type_dependent() {
		return foo(_member);	// foo调用却决模板参数
	}

private:
	int _val;
	type _member;
};

extern int foo(int);
ScopeRules<int> sr0;
分为两种:①定义出template的程序端、②实例化template程序端;
- ①用以专注于一般的模板类;
- ②用于专注特定的实例;
上述中两个foo()调用,在程序定义前有一个foo声明,而在实例化前有两个foo声明;

当使用sr0.invariant()时,内部的foo将调用foo(double);这是为什么呢?

template中,对一个非成员名称(foo)的决议根据name是否与用以实例化该template的参数类型有关而决定,若不相关,则以①来决定,相关则用②;
而该foo()与实例化该类的参数类型无关【代码注释】;

1.3 成员函数的实例化行为是什么?

目前实例化有两种行为:
- 【编译】,code必须在程序文本文件中;
- 【链接】,辅助工具来引导编译器实例化;

【编译器如何找出函数定义】
- 其中Borland从保护template程序文件中查找,或者要求一种文件用来才存放;

【编译器如何能够只实例化程序中用到的成员函数】
- 模拟链接操作,检测哪一个函数真正需要,在将其实例化;

【编译器如何阻止member definition在多个.o文件中都被实例化呢?】
- 产生多个实例,在从链接器中提供支持,只留下其中一个实例,其余的忽略;
- 或者由使用者来引导模拟链接阶段的实例化策略,决定哪些实例才是需要的;

cfront3.0提供一个由使用者驱动的自动实例化机制;

【directed-instantiation机制】
- 一个程序的原始码被编译时,最初不产生任何实例,但其相关信息将被产生于类文件中;
- 当类文件链接一起时,一个prelinker程序将被执行,用于检查对象文件;
- 对每一个参考到template实例而该实例却没有定义时,prelinker将必要的程序实例化操作指定给特定文件(.ii文件);
- prelinker重新执行编译器,编译.ii文件中将其都实例化;
- 所有的对象文件都被链接成一个可执行文件;

- 该机制的主要成本在于第一次编译时.ii文件的设定时间,及次要的对每一个编译后执行prelinker;

【当一个类被用于几十个文件中,编译器如果确保只有一个虚表实例被产生?】
- 每个虚函数的地址都被置于active classes的虚表中;
- 若取得函数地址,表示虚函数定义必定出现在程序的某个地点,否则链接失败;
- 且改函数只能由一个实例,否则链接失败;
- 故将其放入定义改类的第一个非内联、非纯虚函数的文件中;
- 虚函数被实例化,在类的实例化点之后;

2、异常处理(Exception Handling)

支持EH,则编译器将要找出catch子句,且需要跟踪程序堆栈中每一个函数做作用区域;如果是类EH,则可能要负责其虚构、清理等动作;
EH需要编译器产生的数据结构和执行期的一个exception library:
- 为了维护执行速度,则需要在编译时间构建数据结构,这膨胀程序大小;
- 为了维护程序大小,则需要在执行期建立数据结构,这会影响执行速度;
- 故编译器必须在上面做出抉择;

2.1 EH简介

EH由以下三个组成:
- throw子句,发出一个exception;
- catch子句,没一个子句就是一个EH,处理某种类型的exception;
- try区段;
当一个exception抛出时,控制权会从函数调用中被释放出来,寻找catch子句;

2.2 对EH的支持

当一个exception发生时,系统会执行:
- 检验发生throw操作的函数;
- 决定throw操作是否发生在try区段;
- exception type域catch子句比较;
- 交到catch子句;

如何将exception type和每一个catch type比较

编译器必须为此产生一个类型描述器(如PTTI),对exception的类型进行编码;

3、执行期类型识别

class node {};

class type : public node {};
class fct : public type {};
class gen : public type {};

void simplify_conv_op(type pt) {
	fct pf = fct(pt);
}
在cfont2.0前conversion运算符不能被重载,且上述函数(simplify_conv_op)内转换也是安全的;

3.1 保证安全的向下转换操作

缺乏一个保证安全的向下转换,需要额外负担:
- 需要额外的空间以存储类型信息;
- 需要额外的时间以决定执行期的类型;

如何解决向下转化:
- 使用关键词dynamic_cast;
- 通过声明一个或多个虚函数来区别class声明;

3.2 dynamic_cast

该运算符可以在执行期决定真正的类型;
使用它,是取出vptr[0]的类型描述器信息进行转化;

将该运算符使用在reference上

当使用指针时,转换失败将会被设置为0,而引用却不行,若设置为0,将会引起临时性对象被产生出来;
那会如何处理呢?
如果转换失败,则将会抛出一个bad_cast exception;

3.3 typeid

该运算符在执行期查询某个类型的信息;
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-05-11 16:14:51  更:2022-05-11 16:15:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 22:54:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码