友元类
1.友元类的声明
class Tv{
friend class Remote;//友元类就代表这肯定是一个类,无须前向声明Remote。
};
class Remote{
...
};
2.友元成员函数
不想使用友类所有函数都变成友元,可以使用友元成员函数。
!!编译器本身的符号解析和编译时按顺序来的,导致友元成员写起来要注意顺序。
class a ; //a要前向声明,否则b中不知道是什么
class b {
public:
void fn(a& temp); //b中使用类型为a的对象temp
};
class a {
private:
int num; //声明a中的数据num
public:
friend void b::fn(a& temp);//声明b中的函数为友元
};
inline void b::fn(a& temp) { //此刻才有num的定义,才能补全该函数
cout << temp.num << endl;
}
嵌套类
如果嵌套类是在另一个类的私有部分声明的,则只有后者能够使用它,如下。
class a{
private:
class b{
};
public:
b temp;
};
其余的保护还有公共属性方面,和基本的数据成员的访问权限是一样的。
异常abort
#include<iostram>
#include<cstdlib> //异常的头文件
using namespace std;
int main(){
double a,b;
scanf("%lf%lf",&a,&b);
if(a==-b){
cout<<"exception\n";
abort();//调用abort函数直接终止当前进程。
}
cout<<1.0/(a+b);
return 0;
}
try..catch
try{
fn();
}
catch(const char *s){
}
void fn(){
throw "a exception";
}
没有try处理的throw
如果引发了一场却没有try块匹配或没有匹配的处理程序的时候,默认情况下,程序最终将调用abort()函数。
多个catch块
除了字符串之外,throw可以返回一切类型,同时使用多个catch进行捕获进行对应的处理,没有匹配类型不会进行转换,会调用 abort()函数
class temp{
public:
int num;
};
try{
fn();
}
catch(const char *s){
....
}
catch(const temp& s){//s只是一个副本,因为原本在栈解退的时候析构了。继承异常的时候,此处使用引用,派生类要放在前面。
....
}
cathc(...){//使用省略号捕获一切异常
}
void fn(){
throw temp();
}
栈解退
try {}捕获的异常不一定是在下一层函数,反是在这个过程中throw的异常都会被捕获到。 从引发异常的函数条到包含try块和处理程序的函数,涉及到栈解退。
栈解退:函数由于出现异常而终止。陈旭将释放栈中的内存,但不会在释放栈的第一个返回地址后就停止,而是继续释放栈,直到找到一个位于try块中过得返回地址。
!!栈解退会导致内存泄漏,如下程序
void fn(){
int *ptr=new int[10];
...
if(xxx)
throw exception();
...
delete []ar; //栈解退导致此句来不及执行。
}
!!避免方式,使用try..catch处理,
void fn(){
int *ptr=new int[10];
...
try{
if(xxx)
throw exception();
}
catch(exception& ex){
delete []ar;
throw;
}
...
delete []ar; //栈解退导致此句来不及执行。
}
RTTI
RTTI(runtime type identification)运行时确定类型
RTTI函数值适用于包含虚函数的类
dynamic_cast转化
转化的类型如果是继承中的高层类(派生)转给底层类,是安全的,否则不安全,dynamic_cast在不安全转化的时候将会返回空指针。
class a{...
virtual void fn(){...}
...};
class b:public a{...};
class c:public c{...};
a* ao=dynamic_cast<a*>(new b); //ok
b* bo=dynamic_cast<a*>(new a); //null
//dynamic_cast对于引用,不安全的时候会出现异常
try{
a& ao=dynamic_cast<a& > ao1;
}
catch (const exception& e){
}
typeid
返回的是一个type_info的对象的引用,type_info是一个记录了对象类型的结构,其中含有成员函数name()可以指出当前类的名字,并重载了 == 和 !=运算符
运算符返回一个指出对象的类型的值
a ao;
b bo;
type_id(ao) == type_id(bo); //0
cout<<type_info(ao).name()<<endl;//class a