友元类
友元类即将类作为另一个类的友元。
例如遥控器可以改变电视机的状态,但又不是电视机的一部分,也不属于电视机,所以可以将遥控器作为电视机的友元。
友元类的声明:使用friend class Remote;可以位于公有,私有,保护都行
class Tv {
public:
friend class Remote;
Tv();
bool onoff();
}
class Remote {
private:
int mode;
public:
void set_chan(Tv & t, int c) {t.channel = c;}
}
友元成员函数
也可以只将Remote::set_chan()左右Tv的友元函数
class Tv {
friend void Remote::set_chan(Tv & t, int c);
}
异常机制
异常处理由三部分组成:
1 引发异常
2 使用处理程序捕获异常
3 使用 try 块
void exceptionfun(int a) {
if(a == 0) {
throw "throw exception a == 0";
cout << "exceptionfun 1" << endl;
}
cout << "exceptionfun end" << endl;
}
void startExceptionText() {
try {
exceptionfun(0);
cout << "startExceptionText 1" << endl;
} catch ( const char * s) {
cout << s << endl;
}
cout << "startExceptionText end" << endl;
}
关键字 throw 是抛出(引发)异常,是跳转,即命令程序跳转到另一条语句(跳转到对应的catch)。throw 随后的值(例如字符串或者对象)指出了异常的类型,将和catch后边括号的参数类型对应(有点像函数)。
catch 关键字表示捕获异常,catch(类型声明),指出随后的异常处理程序要处理的异常类型。
异常被引发时候,程序应跳转到对应类型的catch块执行,try后边的语句也不会执行。当异常与该处理程序匹配时,程序将执行catch括号中的代码块。
执行throw相当于执行return语句,因此将终止当前函数的执行。但throw不是将控制权返回给调用函数,而是导致程序沿函数的调用序列后退,直到找到包含try块的函数。
将对象作为异常类型
可以将对象作为异常类型,如下,携带更多的信息
void exceptionfun(int a) {
if(a == 0) {
string s = "throw exception!!";
throw s;
cout << "exceptionfun 1" << endl;
}
cout << "exceptionfun end" << endl;
}
void startExceptionText() {
try {
exceptionfun(0);
cout << "startExceptionText 1" << endl;
} catch ( const string& s) {
cout << s << endl;
}
cout << "startExceptionText end" << endl;
}
栈解退
如果函数由于出现异常(而不是函数返回)而终止,则程序也将释放栈中的内存,但是不会在释放栈中的第一个返回地址后停止,而是继续释放栈,直到找到一个位于try块中的返回地址,随后,控制权将转到块尾的异常处理程序,而不是函数调用后面的第一条语句,
对于栈中的自动类对象,类的析构函数将被调用
throw 语句将控制权向上返回到第一个包含能够捕获相应异常的try-catch组合。
引发异常时编译器总是创建一个临时的拷贝,即使异常规范和catch块中指定的是引用。
void exceptionfun(int a) {
if(a == 0) {
string s = "throw exception!!";
throw s;
cout << "exceptionfun 1" << endl;
}
cout << "exceptionfun end" << endl;
}
void startExceptionText() {
try {
exceptionfun(0);
cout << "startExceptionText 1" << endl;
} catch ( const string& s) { //传入的是副本
cout << s << endl;
}
cout << "startExceptionText end" << endl;
}
可以使用省略号来捕获任何异常
tey{} catch(...) {}
RTTI:
如果指向的对象(*pt)的类型为Type,或者是从Type直接或者间接派生来的类型,则下边的表达式将指针pt转换为Type类型的指针:
dynamic_cast<Type *>(pt)
否则,结果为0,即空指针。
if(ps = dynamic_cast<Type *>(pt)) {
ps->Say();
}