分享
 
 
 

C++对象模型之七 模板 异常 RTTI笔记

王朝c/c++·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

C++对象模型之七 模板 异常 RTTI笔记

下面关于模板的三个问题:

1 模板的声明时会发生什么

2 如何实例化出类对象内联成员

3 如何实例化出成员,模板成员函数,模板静态成员.

Template <class T>

Class point

{

public:

enum Status { unallocated, normalized };

point (T x=0.0,T y=0.0, T z=0.0);

~point ();

void * operator new ( size_t );

void * opertaor deleted (voide * , size_t );

private:

static point<T> * freeList;

static int ChunSize;

T _x, _y, _z;

};

当编译器看到template class 声明时,它什么反应也没有,上述的静态数据成员,嵌套枚举 不可用. 虽然enum status 的真正的类型在所有的point实例中都一样.但是它们必须通过模板point类的实例来存取和操作.

Point <float >:: Status S; // OK

Point ::Status S;//Error

指针: const point < float > * ptr = 0; 不会实例化;

引用: const point < float > & ref = 0; 会实例化

è point < float > temp ( floa t (0 ) ); const point < float > & ref = temp;

模板的错误报告: 所有的语法错误被检测出来,但不做类型检查.

模板中的名称解决方式

extern double foo ( double ); //类S的定义

template < class T>

class S

{

public:

void invariant () { member = foo ( val); }

T dependent() { return foo ( member) ;}

private:

int val;

T member;

};

extren int foo (int );

S<int> S1;

S1.invariant();

S1.dependent();

模板中对于成员名称的解决结果时根据这个名称的使用是否与”用以实例化出该模板的参数类型有关” 而决定.没有关就采用类的定义来解决, 有关就采用实例化的参数类型.

因此: S1.invariant();中的foo 调用的 extern double foo ( double ); 因为void invariant () { member = foo ( val); }中的val 是int val; 类型无关.而 S1.dependent(); 中的foo 调用的 extern int foo ( int );因为T dependent() { return foo ( member) ;}中的member 是T member; 类型有关.

成员函数的实例化

只有在成员函数使用时后C++标准才要它们被实例化出来.但是并不精确遵循.愿意如下:

1 空间和时间的考虑. 如果类中有100个成员函数,但你的程序只针对某个类型的7个函数,那么其他的193个函数都要被实例化将花费大量的时间和空间.

2 尚未实现的机制,并不是一个模板实例化出来的所有类型就一定能够完整支持一组成员函数所需的所有运算符.

Point < float > *ptr = new point < float >;

用到了 void * operator new ( size_t ); point (T x=0.0,T y=0.0, T z=0.0);

目前编译器有两个策略: 1是编译时期程序代码必须在程序文本文件中备妥当,2 是连接时用工具引导编译器实例化行为.

1 编译器如何找出函数的定义?

1是包含在模板程序文本中,2 要求一个文件命名规则.

2 编译器如何只实例化程序中用到的成员函数?

1 根本忽略,把一个已经实例化的类所有的成员函数都生产出来. 2仿真连接操作: 检测哪个函数真正需要.

3 编译器如何阻止成员定义在多个obj文件中都被实例化?

1 产生多个实例在连接时候只留下一个. 2 由使用者来引导”仿真连接阶段”的实例.

Borland 支持所有问题的第一中方法.

异常处理

一般而言异常处理机制需要与编译器所产生的数据结构以及执行期的一个异常库精密合作.

编译器在程序速度和大小方面做出选择

1 为了维持运行速度,编译器可以在编译时期建立起用于的数据结构.但编译器可以忽略这些结构直到异常

2 为了维护程序大小,编译器可以在执行期建立起用于的数据结构, 但编译器只有在必要的时候才建立数据结构.

异常可以不程序划分为多个区域: try block 以外 和try block以内以及整个区域.

void mumble ( void * arena )

{

point *p = new point ;

try

{

smlock ( arena );

}

catch (…)

{

smunlock ( arena );

delete p;

throw ;

}

smunlock (arena);

delete p;

}

为什么 point *p = new point ;不在try block以内? 因为它之前没有什么要释放的东西.虽然它自己也会抛出异常,但是它会自己处理调资源释放的问题.

支持异常会使成员对象或基类子对象的类的构造函数复杂化. 比如: 类X有成员对象 A,B,C.它们都有一对的构造和析构函数. 但A的构造函数抛出异常,那么A,B,C的析构不用调用. 但 B的构造函数抛出异常,那么A的析构要调用,C的析构不用调用. 一样的是 point3d *ptr = new point3d [512]; 假如第100个元素抛出异常,那么前99个要调用析构,后面的就不用调用.

当一个异常发生时,编译器要完成以下事情:

1 检验throw 操作函数

2 决定 throw 操作是否发生在try 区域中

2.1 如果是 编译器把异常类型和每一个catch比较

2.2 如果比较吻合,流程控制权交到catch中

3 如果 throw 操作不发生在try 区域中 或者没有一个catch吻合 那么系统会做 1 释放所有本地存在的对象, 2 从堆栈中将当前的函数展开掉 3 进行到程序堆栈中的下一个函数,然后重复2-3

决定 throw 操作是否发生在try 区域中 函数中会生成区域统计表

如果是 编译器把异常类型和每一个catch比较 系统会采用类型描述器(RTTI)

当异常被丢出时,异常对象会放在相同形式的异常数据堆栈中,从throw传给catch 的是 异常对象地址和类型描述器.一般catch( ex &p) 基本上采用引用 如果是对象,有能发生切割.

对象大小

没有异常

有异常

百分比

Borland

86.822

89.510

3%

Microsoft

60.146

67.071

13%

Symantec

69.786

74.826

8%

执行速度

Borland

78

83

6%

Microsoft

83

87

5%

Symantec

94

96

4%

运行期类型识别(RTTI)

向下兼容:

RTTI是后来引进的,并没有使用新的关键字,而是如果声明的虚函数就会有RTTI。

动态类型转换:dynamic_cast可以在运行期决定类型,如果成功将传回指针否则是0 比静态转换成本要贵的多,但是也安全多了。Dynamic_cast < Type > ( &pt) 如果是引用失败后返回的是bad_cast异常。

TYPEID:

使用它可以同样达到引用的目的

if ( typeid (rt)== typeid (fct))

fct &rf=static_cast<fct&>(rf);

typeid 转会来的const 引用 类型为type_info : bool type_info ::operator==(const type_info&) cosnt;

class type_info

{

public:

virtual ~type_info();

bool operator==(const type_info&) const;

bool operator!=(const type_info&) const;

bool before (const type_info &) const;

const char *name() const;

private:

type_info (const type_infor&);

type_info & operator = (const type_info &);

};

RTTI 适合与多态 type 适合于普通类和一般类型。

曾牧暗鲨 && 大白鲨 2003-8-19

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有