深入探索C++对象模型之七 --- 站在对象模型的尖端
来源:互联网 发布:皇室战争辅助软件 编辑:程序博客网 时间:2024/06/04 23:24
深入探索C++对象模型之七 — 站在对象模型的尖端
template instantiation 模版具现化
template、exception handling和runtime type idetification
Template
模版只是定义了函数
tempalte的声明
当我们声明template的时候,编译器对于声明代码是不做任何处理的,只有在程序中使用到了具体类型的类或者函数的时候,编译器才会根据模版定义具现化该类型参数的class和member function。编译器会根据出现的参数类型instantiation一个具体的实体。
如果在程序中使用到模版类中的static data member。必须指定patter,如:
template <class T>class Point { ...private: static int value;}
我们如果想访问value的话必须
Point<int>::value
或者Point<double>::value
, 而不能是Point::value
.这会使得编译器产生针对int或者double的instantiation实体。否则的话编译器不做任何处理自然也不存在所谓的static data member实体。
其次,我们如果使用point的话是不会产生instantiation实体的,如Point<float> *ptr=0
,这的确是一个Point<float>
指针,但是这个不是一个Point<float>
class object,不关心该object的内部布局。而使用refenece的话则必须要instantiation实体,因为reference是class object的引用,因此必须要产生instantiation实体。member function也不应该全部被“实体”化,只有在member functions被使用的时候才会被instantiation。试想如果class中有100个member functions,但是只用到了两三个,那么如果实体化全部的函数将会花费大量的时间和空间。
那么这些member function是在什么时候“具现”出来的呢?要么在编译时期,要么则是在链接时期。
所有与类型有关的校验,如果牵涉到template参数都必须延迟到真正的具现操作时才发生。
Template中的名称决议方式。一个编译器必须保持两个scope context
5.1 scope of template declaration 用于专注于一般的template class。当名称的决议和template参数类型无关的时候就使用该scope
5.2 scope of template instantiation 用于专注于特定的实体。当名称的决议和template参数类型相关的时候则使用该scopeMember function的具现行为
template的特化和偏特化(template specialization and partial specialization)
对于之前提到的template instantiation,在编译时期编译器可以根据你传入的模版参数instantiation实体,并且具现化class member function。但是有时候真对某些类型可能member function的具体行为我们需要重新定义,那么这时候就需要额外限定模版的参数,指定当这种参数类型的时候使用自己特别定制的member function,这就是特化。
而如果template我们只是指定部分的类型那么这就是偏特化。
如下例子:
#include<iostream>using namespace std;class man { private: string name; int data; public: man(string s, int i):name(s),data(i) { } void show() const { cout << "this name is " << name << ", data = " << data << endl; } void setData(int d) { data = d; } int getData() const { return data; }};template <class T>void mSwap(T &t1, T &t2) { T temp = t1; t1 = t2; t2 = temp; cout << "Here are template version " << t1 << "and" << t2 << endl;};int main() { man m1("aa", 99); man m2("bb", 100); mSwap(m1, m2);}
上面的代码编译失败是因为编译器会instantiation一个man的实体,但是man类型没有定义<<
运算符,因此在mSwap最后一行就会编译报错,因此我们就需要针对man这种特别定制mSwap函数,如下:
tempalte <>void mSwap(man &m1, man &m2) { /*do something*/}
如果有非模板函数存在,当匹配度相同的时候优先使用非模板函数。函数模板定制是实例化模板,而不是模板的重载。
异常处理
c++程序中exception handling主要有三个语汇构成:(1)一个thow子句 (2)一个或者多个catch子句 (3)一个try区段
当一个exception被丢出去时,控制权会从函数调用中释放出来,并寻找一个吻合的catch子句,如果找不到的话就使用默认的处理例程terminate().当控制权被放弃后,堆栈中的每一个函数调用都将被推离,这个程序称为unwinding the stack。在每一个函数被推离堆栈之前,函数的local class object的destructor会被调用。
对于在函数内部各个区段间产生的exception,到底是否已经产生local class object以及是否需要释放资源这些都是编译器干的事。
对于每一个被丢出来的exception,编译器都必须产生一个类型描述器,同时编译器还要为每一个catch子句产生一个类型描述器。执行期间exception handle就将这两个描述器进行比较直到找到一个吻合的catch子句处理,或者直到堆栈已经被“unwound”而terminate()已被调用。
如果在catch语句段中再次throw出exception object的话,抛出的仍然是原来一开始的object class,即使在catch中做过处理,catch子句对于exception object的任何改变都是局部性的。
执行期类型识别 RTTI
dynamic_cast可以在执行期决定真正的类型,如果downcast是安全的那么这个运算符会传回适当转型过的指针,而如果downcast是不安全的那么这个运算符传回0。那么dynamic_cast的成本是什么呢?
type_info是C++所定义的类型描述器的class名称,该class中放置着需要的类型信息。virtual table中第一个slot内含type_info object的地址。当需要判断时,这两个比较器会被交给一个runtime library函数比较,告诉我们是否吻合。
程序执行中对一个class指针类型施以dynamic_cast运算符的话,会获得true或false
- 如果传回真正的地址,表示这个object的动态类型被确认了,一些类型有关的操作可以施行于其上
- 如果传回0,表示没有指向任何object,意味着应该以另外一种逻辑施行于这个动态类型未确定的object上
而如果对一个reference施行于dynamic_cast运算符的话,会是另外一个结果:
- 如果reference参考适当的derived class,那么downcast会被执行而程序可以继续进行
- 如果reference并不真正是一种derived class,那么会丢出一个bad_cast exception。
typeid运算符传回一个const reference,类型是type_info。
- 深入探索C++对象模型之七 --- 站在对象模型的尖端
- 深入探索c++对象模型之站在对象模型的尖端
- 深度探索C++对象模型(七)站在对象模型的尖端
- 深入探索C++对象模型 第七章 站在对象模型的尖端
- [读书笔记] 深入探索C++对象模型-第七章-站在对象模型的尖端(上)
- [读书笔记] 深入探索C++对象模型-第七章-站在对象模型的尖端(中)
- [读书笔记] 深入探索C++对象模型-第七章-站在对象模型的尖端(下)
- 深入探讨C++对象模型 之 站在对象模型的尖端
- 深度探索C++对象模型第七章 站在对象模型的尖端
- 深度探索C++对象模型读书笔记-第七章站在对象模型的尖端
- 《深度探索C++对象模型》--7 站在对象模型的尖端
- 深度探索C++对象模型复习和学习 第七章:站在对象模型的尖端
- 【深度探索C++对象模型读书笔记】【第7章】站在对象模型的尖端
- [温故而知新] 《深度探索c++对象模型》——站在对象模型的尖端
- 《深度探索C++对象模型》读书笔记第七章:站在对象模型的尖端
- C++对象模型 ch7 站在对象模型的尖端
- Inside The C++ Object Model(七)站在对象模型的尖端
- 【C++】深度探索C++对象模型之站在对象模型的顶端
- AsyncTask 与 Handler
- 486. Predict the Winner
- ActionBar入门
- Plug-in 自定义扩展点
- 在Ubuntu开发环境上安装Hyperledger Fabric
- 深入探索C++对象模型之七 --- 站在对象模型的尖端
- 无法定位程序输入点 _glutCreateWindowWithExit于动态链接库glut32.dll上
- Java工具类---数组操作ArrayUtil
- 个性化推荐读书笔记
- Plug-in 创建RCP项目
- LeetCode 7. Reverse Integer
- 字符编码
- curses
- 伪类选择器 before 和after的使用 实例 制作圆角