1. 程式人生 > >C++友元與異常

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;
}