C++友元與異常
阿新 • • 發佈:2019-02-09
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的成員函式。所以,可以按照如下的順序:
- 宣告類B
- 定義類A,宣告但不實現A::F
- 定義類B,設定A::F為友元
- 實現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;
}