可以將類b宣告在另乙個類中。在另乙個類a中宣告的類b被稱為巢狀類(nested class)。
類a的成員函式可以建立和使用巢狀類b的物件。
當且僅當宣告為公有部分時,才能在類a的外面使用巢狀類。而且必須使用作用域解析運算子。(舊版c++不支援巢狀類概念)
對類進行巢狀和包含並不同。包含意味著將類c物件作為類a的成員。而對類b進行巢狀不建立類成員,而是定義了一種型別,該型別僅僅在包含巢狀類宣告的類a中有效。
對類進行巢狀通常是為了幫助實現另乙個類,並避免名稱衝突。
1class
queue23
;1213 }
結構是其成員在預設情況下公有的類。結構可以理解成一種特殊的類。
所以node實際上可以看成巢狀類。但該定義沒有充分利用類的功能。
具體來說,它沒有顯式建構函式。接下來進行補救。
queue的方法enqueue建立了node:
1bool queue::enqueue(const item &item)
2
上述**建立node後,顯式地給node成員賦值,這種工作更適合由建構函式來完成。
於是可以改寫node如下:
1class
queue210
};11
...
12 }
該建構函式節點的item成員被初始化為i,並將next指標置為0,這是c++編寫空值指標的方法之一。
接下來,需要使用建構函式重新編寫enqueue():
1bool queue::enqueue(const item &item)
2
這使得enqueue()的**更短,也更安全,因為它自動進行初始化,無需程式設計師記住應該做什麼。
這個例子在類宣告中定義了建構函式。假設想在方法檔案中定義建構函式,則定義必須指出node類,
這是通過兩次作用域運算子來完成的;
queue::node::node(const item & i):item(i),next(0)
巢狀類和訪問許可權
巢狀類的宣告位置決定了巢狀類的作用域。即它決定了程式的那些部分可以建立這種類的物件。
其次,和其他類一樣,巢狀類的公有部分、保護部分、私有部分控制了對類成員的訪問。
在哪些地方可以使用巢狀類以及如何使用巢狀類,取決於作用域和訪問控制。
1、作用域
如果巢狀類是在類的私有部分宣告的:
則只有類的私有部分知道它,在前乙個例子中,被巢狀在queue宣告中的node類就屬於這種情況。
queue成員可以使用node物件和node物件的指標,但是程式的其他部分甚至不知道存在node類。
而對於從queue派生而來的類,node也是不可見的。因為派生類不能直接訪問積累的私有部分。
如果巢狀類是在類的保護部分宣告的:
則該巢狀類對於後面這個類是可見的,但是對於外部世界則是不可見的。
在這種情況下,派生類知道巢狀類,病可以直接建立這種型別的物件。
如果巢狀類是在類的公有部分宣告的:
則後者、後者的派生類以及外部世界使用它,因為它是公有的。
然而,由於巢狀類的作用域為包含它的類,因此在外部世界使用它時,必須使用類限定符。
巢狀結構和列舉的作用域如此相同。其實,很多程式設計師都使用公有列舉來提供可供客戶程式設計師使用的類常數。
作用域就是指這個物件(類、列舉)可見的範圍,有效的範圍。
2、訪問控制
類可見之後,起決定作用的就是訪問控制。
類宣告的位置決定了類的作用域或可見性。類可見後,訪問控制規則(公有、保護、私有、友元)將決定程式對巢狀類成員的訪問許可權。
在queue類宣告中宣告node並沒有賦予queue類對node類的訪問特權。
因此queue類物件只能顯式地訪問node物件的公有成員。
由於這個原因,在queue示例中,node類的所有成員都被宣告為公有的。
這樣有悖於應將資料成員宣告為私有的慣例,但node類是queue類內部實現的一項特性,對外部實際不可見,這是因為queue類是在queue類的私有部分宣告的。
所以,雖然queue的方法可以直接訪問node成員,但使用queue類的客戶不能這樣做。
模板中的巢狀
模板很適合用於諸如實現queue等容器類。
將queue類定義轉換為模板時,是否會由於它包含巢狀類而帶來問題?答案是不會。
1-- queue template with a nested class
2#ifndef queuetp_h_
3#define queuetp_h_
45 template
6class
queuetp7;
10//
node is a nested class definition
11class
node
1217
};18 node *front;
19 node *rear;
20int item; //
current number of items in queue;
21const
int qsize; //
maximum number of items in queue;
22 queuetp(const queuetp & q): qsize(0
) {}
23 queuetp & operator=(const queuetp & q)
24public
:25 queuetp(int qs=q_size);
26 ~queuetp();
27bool isempty() const;30
bool isfull() const;33
int queuecount const;36
bool enqueue(const item & item); //
add item to end
37bool dequeue(item & item); //
remove item from front
38};
3940
41#endif
1//queuetp methods
2 queuetp::queuetp(int
qs): qsize(qs)37
89 template
10 queuetp::~queuetp()
1119}20
2122 template
23bool queuetp::enqueue(const item &item)
2437
3839 template
40bool queuetp::dequeue(item &item)
41
在模板中node是利用item型別來定義的。
下面宣告將導致node被定義成用於儲存double值:
queuetpdq;
而下面的宣告將導致node被定義成用於儲存char的值:
queuetpdq;
這兩個node類將在兩個獨立的queuetp類中定義,因此不會發生名稱衝突。
即乙個節點的型別為queuetp::node
另乙個節點的型別為queuetp::node
接下來用乙個小程式測試一下:
1-- using a queue that has a nested class
23 #include 4 #include
5 #include "
queuetp.h"6
7int
main()
824 cout<<"
the queue is full.processing begins!\n";
2526
while(!cs.isempty())
2731
return
0;
32 }
C 巢狀類匿名類與密封類
一 巢狀類 1.概念 在 c 中可以將乙個類定義在另乙個類的內部 外面的類叫 外部類 內部的類叫 巢狀類 巢狀類和普通類相似,只是宣告的位置比較特殊。2.注意事項 如果想例項化內部類的話,需要使用 外部類名.內部類名 的方式訪問到內部類。二 匿名類 1.概念 如果某個類的例項物件只會使用到一次,可以...
C 類的巢狀
巢狀類 nested class 是在類中定義的類。以下把擁有內嵌類的類稱為外部類。巢狀類分為靜態巢狀類和非靜態巢狀類,其中非靜態巢狀類也被稱為內部類。巢狀類在 uml中是composite的另外一種 表示形式,表示耦合度更高,並且與外部類更加緊密。一般類的訪問修飾符可以定義為預設的internal...
C 類的巢狀
巢狀類 nested class 是在類中定義的類。以下把擁有內嵌類的類稱為外部類。巢狀類分為靜態巢狀類和非靜態巢狀類,其中非靜態巢狀 類也被稱為內部類。巢狀類在uml中是composite的另外一種 表示形式,表示耦合度更高,並且與外部類更加緊密。一般類的訪問修飾符可以定義為預設的internal...