或者系統只提供16個可分發出去的檔案描述符,如何確保檔案描述符物件存在的數目不能超過16個。
在具體的應用過程中,我們可能需要限制某個類所產生的物件數量。
下面我們先從簡單的問題的開始。
1.如何允許建立零個物件?
例項化乙個物件時,將呼叫乙個建構函式,因而阻止建立某個類的物件,最容易的方法就是把該類的建構函式宣告在類的private域。**示例如下:
1class
cantbeinstantiated
2;
2.如何允許建立乙個物件?
將類的建構函式宣告為private後,每個使用者都沒有權力建立物件,但實際應用的需求是我們需要建立乙個物件,因此我們需要選擇性地放鬆這個限制。
對於宣告為private的建構函式,我們可以引入友元函式或成員函式來進行訪問,並利用靜態成員變數來保證物件的唯一,具體實現**如下:
//使用友元函式來訪問私有建構函式
namespace
printingstuff
;
printer&theprinter()
}using
printingstuff::theprinter;
theprinter().reset();
theprinter().submitjob(buffer);
1//使用靜態成員函式來訪問私有建構函式
2class
printer3;
12 printer&printer::theprinter()
1317
18printer::theprinter().reset();
19 printer::theprinter().submitjob(buffer);
上述兩種實現思想是一致的,最終都是通過theprint()函式來完成客戶端與系統印表機互動訪問的需求。theprinter()函式的實現有兩點值得注意:
1)唯一的printer物件是位於函式裡的靜態成員而不是在類中的靜態成員。在類中的靜態物件有兩個缺點,乙個總是被構造(和釋放),即使不使用該物件;另乙個缺點是它的初始化時間不確定。
2)theprinter()函式沒有宣告為內聯函式,因為內聯意味編譯器用函式體代替對函式的每乙個呼叫,這樣會導致函式內的靜態物件在程式內被複製,可能會使程式的靜態物件的拷貝超過乙個。
上述兩種方法,都解決了允許建立乙個物件的問題,但無法解決允許建立多個物件的限制問題。
3.如何限制允許建立多個物件?
我們可以換一種思路,不利用友元函式或成員函式來作為建立物件的中介,而引入計數器簡單地計算物件的數目,一旦需要太多的物件,就丟擲異常。具體**實現如下:
1class
printer
2; //
當需要的物件過多時,丟擲的異常類
5printer();
6 ~printer();
7...
8private:9
static
size_t numobjects;
10static
size_t maxobjects;
11 printer(const printer&rhs);
12};
1314 size_t printer::numobjects = 0
;15 size_t printer::maxobjects = 10;16
printer::printer()
1722
...23 ++numobjects;24}
25 printer::~printer()
26
此法的核心思想就是使用numobjects跟蹤printer物件存在的數量。當構造物件時,它的值就增加,釋放物件時,它的值就減少。如果試圖構造過多的物件,就會丟擲乙個toomanyobjects型別的異常。通過maxobjects設定可允許建立物件的最大數目。
以上兩種方法基本上可以滿足,限制物件數目的要求。但是具體應用中,仍會出現問題,上述兩種方法無法解決。如下面**所示:
1class colorprinter:public
printer2;
56printer p;
7 colorprinter cp;
1class
cpfmachine2;
9cpfmachine m1;
10 cpfmachine m2;
利用計數器的方法,上述**中,都將會產生多個printer物件,由printer被作為基類或者被包含於其他類中,導致其他物件的構造時,隱藏構造printer物件。這主要是計數器方法無法區分物件存在的三種不同環境:只有它們本身;作為其他派生類的基類;被嵌入在更大的物件中。
利用theprinter()函式的方法,把printer物件的數量限制為乙個,這樣做的同時也會讓我們每一次執行程式時只能使用乙個printer物件。導致我們不能在程式的不同部分使用不同的printer物件。如下面偽**所示:
1建立printer物件p1;
2使用p1;
3釋放p1;
4建立printer物件p2;
5使用p2;
6釋放p2;
7 ....
4.如何解決兩種方法存在的問題?
思路:將兩種方法結合,將建構函式宣告為private,限制其被繼承和被包含於其他的類,解決計數器的問題,並提供偽建構函式作為訪問物件的介面,並統計物件的個數,來解決限制構造多個物件和程式不同部分使用不同物件的問題。具體**實現如下:
1class
printer2;
5//偽建構函式
6static printer*makeprinter();
7static printer* makeprinter(const printer&rhs);
8...
9private:10
static
size_t numobjects;
11static
const
size_t maxobjects;
12printer();
13 printer(const printer&rhs);
14};
1516 size_t printer::numobjects = 0;17
const size_t printer::maxobjects = 10;18
printer::printer()
1924
...25
}26 printer::printer(const printer&rhs)
2732
...33
}34 printer*printer:makeprinter()
3538 printer* printer::makeprinter(const printer&rhs)
3942 printer *p1 = printer::makeprinter();
到目前為止,對於限制物件數目的問題,應該是大功告成。但是仍不能滿足工程性上的應用,例如我們有大量像printer需要限制例項數量的類,就必須一遍又一遍地編寫一樣的**,每個類編寫一次。作為程式設計師,應該避免這種重複性的工作。
5.乙個具有物件計數功能的基類
針對重複性工作的問題,解決思路是:構造乙個具有例項計數功能的基類,讓像printer這樣的類從該基類繼承,利用派生類物件的構造,需要先構造基類物件的特點,通過隱藏的基類實現計數功能。具體實現如下:
1 template2class
counted3;
6static
intobjectcount()710
protected:11
counted();
12 counted(const counted&rhs);
13 ~counted()
1417
private:18
static
intnumobjects;
19static
const
size_t maxobjects;
20void
init();
21};
2223 template
24 counted::counted()
2528
29 template30 counted::counted(const counted&)
3134
35 template
36void counted::init()
3742
43class printer::private counted44
;
c 限制某個class所能產生物件數量的方法
1.產生零個或乙個物件 將建構函式與拷貝建構函式宣告為私有成員,並宣告乙個友元函式,在友元函式中宣告乙個靜態成員,呼叫建構函式,並返回乙個靜態成員的引用。另一種方法就是設定乙個計數器,初始化為0.在建構函式中 1,在析構函式中 1,每次保證只有乙個物件。2.不同物件的構造狀態 上述第二種方法在繼承關...
M26 限制某個class所能產生的物件數量
1 每當產生乙個物件,必定呼叫構造方法。因此,禁止產生物件的做法就是,將所有的構造方法宣告為private。2 只有在類的內部才可以訪問private成員,有兩層含義 在類的內部可以訪問this的private成員,同時可以訪問同類物件的private成員。3 將構造方法宣告為private,只是限...
php 限制類的物件型別
事實上,採用哪種處理引數型別的策略,取決於任何潛在bug的嚴重程度。通常php會根據語境自動轉換大多數基本資料型別。因此,你需要在檢測型別 轉換型別和依賴良好清晰的文件 無論決定用哪一種,都應該提供文件 之間仔細權衡。無論你如何解決這類問題,都要認真思考一件事情 型別處理。php是一種弱型別的語言,...