C++友元与异常

C++ Primer Plus读书笔记

友元

  • 友元不仅可以是一个函数,并且可以是类,友元类的所有方法都可以访问原始类的私有成员和保护成员。同时,可以做更加细致的限定:只将特定的成员函数指定为一个类的友元。

1.友元类

  • 友元类在声明的时候需要在被调用的类中声明friend,此后即在这个friend类中随意访问原来类中的private成员了。

  • 也就是说,在某个类中(我)声明另外一个类是朋友,那么这个朋友就可以用我这个类的private。

class ZhuMeng
{
public:
    friend class yanyiquan;
private:
    int a;
};

class yanyiquan
{
public:
    void get_a(ZhuMeng & t){t.a = 1;}
    // 如果是只规定一部分函数作为友元,则
    friend ZhuMeng::a;
    //并且不需要在ZhuMeng类中声明class是friend的。
};
  • 友元类是单向的,一个类是另一个类的友元,但是另一个类不一定是这个类的友元。

  • 友元函数在原始类中应只声明,将定义放在实际定义TV类之后。因为编译器必须在了解原始类之后,才能处理他的友元类,因此是需要前向声明的。

  • 就以TV和Remote两个类为例,Remote类中的方法提到了TV类中的对象,因此TV类需要定义在remote类之前,但是在TV类中,又无法知道Remote是一个类,这样就产生了循环依赖
class Tv;

class Remote{…};

class Tv{…};
  • 举个例子:当将一个类A的成员函数A::F设置成类B的友元时,需要预先定义类A,否则不能将A::F指定为友元。而在定义B之后,才能定义A::F,因为A::F被设为 友元正是为了访问类B的成员函数。所以,可以按照如下的顺序:

    1. 声明类B
    2. 定义类A,声明但不实现A::F
    3. 定义类B,设置A::F为友元
    4. 实现A::F
#include<iostream>
#include<cstdlib>
using namespace std;

class Screen;//前向声明
class Window_Mgr
{
public:
  void reloacate(Screen& s);
};

class Screen
{
  friend void Window_Mgr::reloacate(Screen& s);//必须先定义Window_Mgr,才能将Window_Mgr::relocate设为友元
public:
  Screen(int _x, int _y): x(_x), y(_y){};
  void print()
  {
      cout <<"x: " <<x <<",y: "<<y <<endl;
  }
private:
  int x;
  int y;
};

void Window_Mgr::reloacate(Screen& s)
{
  s.x++;
  s.y++;
}

int main(int argc, char* argv[])
{
  Screen s(0, 0);
  Window_Mgr mgr;
  mgr.reloacate(s);
  s.print();
  system("pause");
  return 0;
}
  • 想要设置两个互为友元的类,则需要在类中互相写friend关键字,同时也要考虑循环依赖的问题,把实现放在后面,也就是实现之前必须先让编译器知道另一个类的内容,如果只是声明,则只需要前向声明即可。

2.嵌套类

  • 类嵌套的意思就是将一个类定义在另外一个类中,与上面写的ZhuMeng类是差不多的,外界能不能使用这个被嵌套的类,则取决于这个类被声明的位置是public还是private。与一般的类是相同的,private和protected在外部不可见,protected和public在继承类中可见。

  • 类的嵌套与包含是两个不同的概念,类的包含是将向另一个类提供类对象,直接使用这个类,而类嵌套则不创建类成员,只是定义了一种类型。

  • 如果想在方法文件中定义构造函数而不是在h文件中,则需要使用两次作用域解析运算符来完成。假设Node类是在Queue类中定义的,则在CPP文件中定义Node类的构造函数时,需要使用下面的语句:
Queue::Node::Node(){}

异常

1.使用abort()

  • abort()函数位于stdlib.h中,其实现大致是这样的:向标准错误流cerr发送消息”abnormal program termination”消息之后直接终止程序,就相当于设定了一个特定输出。

2.异常机制

  • C++异常指的是对程序运行过程中发生的异常情况的一种响应。异常提供了将控制权从程序的一个部分传递到另一个部分的途径,一般来说有下面三个组成部分
    • 引发异常
    • 使用处理程序捕获异常
    • 使用try块
  • 这个异常处理的模板是按照下面的方式来进行的
try{
    //进行一系列判断
    throw ...//这里可以是任意的内容
}
catch(leixing1 x){//这里的类型与前面throw后面直接加的类型是一致的
    //进行操作
}
catch(leixing2 x){//可以有多个catch语句来对应throw出来的不同类型的内容
    //进行操作
}
  • 下面是一个例子

    while(1)
    {
        cin>>k;
        try{
            if(k==-1)
                throw 1;
        }
        catch(int num){
            cout<<"throw"<<num<<endl;
            continue;
        }
    }
  • 如果不清楚异常的具体类型,则可以使用
catch(...){}//三个点就表示了对于任意类型的throw都可以进行处理

3.exception类

  • C++中提供了标准的异常类,需要#include<exception>,标准异常类为exception,该类有个what函数,可以打印异常对象的异常信息。该what函数是虚函数,我们需要继承exception类并重写该what函数,在捕捉异常的时候,我们用父类的引用来接收自定义的标准异常类的子类对象(类型兼容性原则),然后打印该异常信息即可。
  • 它的catch语句可以如下面所写
catch(exception &e){
    cout<<"throw"<<e.what()<<endl;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章