c++primer plus阅读笔记(八)

友元类

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
#include       //异常的头文件
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(new b); //ok
b* bo=dynamic_cast(new a); //null

//dynamic_cast对于引用,不安全的时候会出现异常
try{
    a& ao=dynamic_cast 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()<

你可能感兴趣的:(随笔)