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