1. Exception 机制, 及其实现。
如果没有任何处理语句, 那么程序会怎么样?
答: 没有处理语句, 那么该异常会被系统默认的异常处理程序abort()所捕获, 导致程序终止运行。因为它不在用户定义的异常区域。
有的书上说是被系统的Terminal()所捕获.
如果Exception被一直向上抛, 没有什么Catch语句Catch住这个异常, 程序会怎么样?
如果一个函数抛掷一个异常,但在通往异常处理函数的调用链中找不到与之机匹配的catch, 则该程序通常以abort()函数调用终止。
若f() ->g()->k(), 在K()中发生异常, 直接上传,并最终被其上上层函数f()所捕获, 那么在f()中处理异常后,函数g()和k()都进行堆栈回栈“这里因为调用函数时会进行堆栈的内存分配”, 然后程序在函数f()中继续运行。
通常在设计异常处理时,把实际资源分析(如内存申请或文件打开)通常在程序的低层进行, 当操作失败、无法分配内存或无法打开一个文件时,在逻辑上如何进行处理是在程序的高层,如这里的f(), 而g()则可以把该异常捕获后再向f()抛掷同类的异常, g()则用以进行释放已分配内存提供了机会, 从而达到分层处理, 各自负责, 反映出面向对象的一种机制。
另外在进行错误匹配时,进行的是按数据类型的严格匹配来捕获, 如throw 20, catch(unsigned int)则不能捕获到该异常, 因为20的数据类型是int,而不是unsigned int.
如果直接写catch(), 括号中没有类型, 则会编译通不过, 如果用catch(…), 则能捕获所有异常。
直接用throw; 没有任何类型的传入, 则意为把得到的异常再向上级传入。 类似于些例中的g()。
如果本身没有异常的抛出, 而用的thow; catch(…), 那么catch(…)也无法捕获到这个异常, 会出现和没有任何处理语句的的错误。和下面的错误一致。
如在程序中直接向上抛出throw(1), 没有任何处理语句, 则MFC会弹出Runtime Error.
详细错误信息为: This application has requested the Runtime to terminate it in an unusual way. Please contact the application’s support team for more information.
2. New的机制.
New()主要有两种重载方式: 抛异常的New(), 和不抛异常的New().
int *fixLength = new int[5];
Tdate * int = new int [10];
Tdate * int = new int [20];
全局变量、静态变量、常量存放在全局数据区, 所有类成员函数和非成员函数代码存放在代码区, 为运行函数而分配的局部变量、函数参数、返回数据、返回地址等存放在栈区, 余下的空间都被作为堆区。
Tdate *pd;
Pd = new Tdate(1,1,1999);
Delete(pd);
Student *ps = new Student[100]; //注: 从堆上分配的对象数组,只能调用默认的构造函数,不能调用其化任何构造函数。
Delete []ps;
3. 运行时候、构造函数和析构函数会抛出异常?
运行情况下抛出异常情况
(1) 在成员函数出现异常时,同一个作用域中异常出现点后面还未来得及构造的对象将不会被构造,当然也不会被析构;
(2) 在成员函数出现异常时,同一个作用域中异常出现点前面已经构造的对象也同样会被析构(这是不是更神奇了!)。因此这也显现出C++异常处理不会破坏C++标准中规定的面向对象的特性,当对象出了作用域时,它就必须要被析构,即便它自己本身没出现异常,总之不管是正常的执行过程导致对象退出了作用域,还是其它对象运行时发生了异常而导致自己退出了作用域;
(3) 在成员函数出现异常时,未被影响到的其它作用域中的对象将保持自己原来的执行流程。
构造函数中
虽然C++标准规定构造函数是没有返回值,可我们知道每个函数实际上都会有一个返回值的,这个值被保存在eax寄存器中,因此实际上是有办法通过编程来实现构造函数返回一个值给上层的对象创建者, 如果用标志位来进行是否构造成功的判断, 会引起即便构造失败也会导致析构函数的执行。
(1) C++中通知对象构造失败的唯一方法那就是在构造函数中抛出异常;如果通过设置某一标志量来判断是否出现异常, 则会导致即便失败也会执行析构函数来进行析构。这是很不合理的。
(2) 构造函数中抛出异常将导致对象的析构函数不被执行;
(3) 当对象发生部分构造时,已经构造完毕的子对象将会逆序地被析构;
构造函数中抛出异常的情况可参见: http://se.csai.cn/ExpertEyes/No143.htm
析构函数中抛出异常的情况可参见: http://se.csai.cn/ExpertEyes/200801031105021299.htm
全部异常解析:http://se.csai.cn/category.asp?class=experteyes&page=3
析构函数中(如句柄出错,或都资源重复释放而发生异常)
(1) C++中析构函数的执行不应该抛出异常;
(2) 假如析构函数中抛出了异常,那么你的系统将变得非常危险,也许很长时间什么错误也不会发生;但也许你的系统有时就会莫名奇妙地崩溃而退出了,而且什么迹象也没有,崩得你满地找牙也很难发现问题究竟出现在什么地方;
(3) 当在某一个析构函数中会有一些可能(哪怕是一点点可能)发生异常时,那么就必须要把这种可能发生的异常完全封装在析构函数内部,决不能让它抛出函数之外(这招简直是绝杀!呵呵!);
4. Try{}catch() 与普通的if 返回值判断有什么区别? 主要是针对构造函数来说的, 由于构造函数无返回值, 所以如果构造失败,那么用if可能得到的是NULL, 用try{}catch()效果会更好。
5. Virtual table, 是Virtual 方法实现的根本。
Virtual父类中. 当调用父类的方法时, 它会查询Virtual table找到相应的实现, 即函数入口, 如果子类有实现, 则会修改这个Virtual table, 从而知道在调用时调用的哪个方法
网页说得非常详细http://www.cppblog.com/dawnbreak/archive/2009/03/10/76084.html
6. Smart Vector, 容器类
7. 对于涉及到数组的巧妙算法, 多是需要涉及到巧用下标 , 如Array[array[i]];累加等操作。
8. 判断异常的情况有三种方式
1. Assert(), 只在debug中有效, 不影响程序在release版本中运行。
2. If(){}
异常与If()条件进行处理的区别主要是: 异常是强制处理, 不处理异常则会出现系统不稳定,甚至可能导致系统Crash, 而If()是选择性处理,可以不进行处理也可以不进行处理。
3. Try{} catch()
9. Error类型, 有些什么样的Error类型
内存越界
申请内存不足
除0操作
内存泄露
重复释放内存区域
10. 出现Runtime的Error会怎么样, 为什么出Runtime的Error.
运行时错误, 说明编译时是没有检测到错误发生的。
11. VC++中,使用string类, 则应加
#include <iostream>
using namespace std;
12. 重载一个指针类, 需要重载那些运算符。
至少需要重载: ++, --, &