[語法] 在建構子裡面檢查資料...?

看板C_and_CPP (C/C++)作者 (好人超)時間16年前 (2009/03/29 23:56), 編輯推噓3(305)
留言8則, 4人參與, 最新討論串1/1
這個標題實在不知道要怎麼下 orz 假如我有一個 class 是用來記錄年、月、日的: class Date { public: Date(int y, int m, int d); private: int year, month, date; } 我想要讓使用者藉由建構子傳入年月日來建立這個物件,譬如 Date d(2009, 3, 29); 這樣的使用應該是很直觀的(吧?還是說本來就不該這麼做?) 但是,日期有合法與非法的,譬如以下這很明顯是非法的: Date d(2009, 13, 32); 那我的建構子要怎麼寫,才能讓使用者傳入非法日期時, 讓使用者知道,並且有機會重新建立這個物件呢? 傳統的函式,可以用回傳一個 bool 來告知是否成功建立: bool initDate(Date *d, int y, int m, int d) { // 假設 d 是個 struct, year, month, date 都是公開欄位 // 如果資料都合法,把資料存進d,並return true // 否則 return false; } 這樣只要寫個迴圈就可以檢測了: int y, m, d; Date date; do { // 讓使用者輸入資料 }while (!initDate(&date, y, m, d)); 但是 constructor 不能回傳資料,因此不能這樣做。 我想過一個辦法是設定 flag,但是這樣很醜 orz 現在想到的另一個辦法是用 exception : Date::Date(int y, int m, int d) { this->year = y; if (m <= 0 || m >= 13) throw "月份輸入錯誤"; else this->month = m; if (d <= 0 || d >= 32) throw "日期輸入錯誤"; else this->date = d; } 類似這樣的作法。caller那邊再負責try-catch就好。 但我一直很遲疑,這樣做到底對不對,好不好… 常常看到 exception 不該用在常態的資料檢測,還有它的效能問題...?? 類似的問題,假設我自己寫了一個 String 類別 我的建構子允許傳入某些東西初始化,但是同樣有參數不合法的可能 class MyString { public: MyString(...); // 可以用某些東西來初始化 private: char *str; }; MyString::MyString(...) // 只是舉例,請不要在意 ... ,就當作是某些東西吧 XD { str = new char[1000]; // 配置空間,大小是亂寫的 if (參數有問題,不合法) 停止建構物件,告知使用者錯誤... } 類似這樣的程式碼,又該怎麼寫呢? 其實這個例子舉得不好,因為只要把 new 的動作移到判斷之後就可以了 但是如果我一定要先配置空間,再判斷,再填資料 這個時候發現參數錯誤,又該怎麼安全的結束建構動作呢? 我試過,如果在這裡丟出例外,並不會呼叫解構子。 也就是說,就算把 delete[] 放在解構子,也無法釋放建構子裡配置的空間。 那我該怎麼做會比較好??還是我根本就不該寫出這樣的架構?? 這個問題困擾我好久了,請各位不吝指教 orz 問題有點長,先感謝願意看到這裡的您。 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 59.104.63.103 ※ 編輯: james732 來自: 59.104.63.103 (03/29 23:58)

03/30 00:01, , 1F
throw exception 就好了
03/30 00:01, 1F

03/30 00:01, , 2F
完全不該用exception的地方只有少數幾個而已
03/30 00:01, 2F

03/30 00:02, , 3F
感謝回覆 請問有哪幾種情況??可否給點關鍵字讓我去找??
03/30 00:02, 3F

03/30 00:02, , 4F
Effective有說 不可在解構子中丟出例外 但我覺得
03/30 00:02, 4F

03/30 00:03, , 5F
也不要在建構子中丟出例外
03/30 00:03, 5F

03/30 00:03, , 6F
然後, 資源請全部用類似Smart Pointer的資源管理物件
03/30 00:03, 6F

03/30 00:04, , 7F
包起來, 這是最安全的方式
03/30 00:04, 7F

03/30 23:37, , 8F
ctor 丟 exception 很 OK 的,不然你要怎麼回報錯誤?
03/30 23:37, 8F
文章代碼(AID): #19pveO6x (C_and_CPP)
文章代碼(AID): #19pveO6x (C_and_CPP)