[語法] 在建構子裡面檢查資料...?
這個標題實在不知道要怎麼下 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
03/30 00:01, 1F
→
03/30 00:01, , 2F
03/30 00:01, 2F
→
03/30 00:02, , 3F
03/30 00:02, 3F
推
03/30 00:02, , 4F
03/30 00:02, 4F
→
03/30 00:03, , 5F
03/30 00:03, 5F
→
03/30 00:03, , 6F
03/30 00:03, 6F
→
03/30 00:04, , 7F
03/30 00:04, 7F
推
03/30 23:37, , 8F
03/30 23:37, 8F
C_and_CPP 近期熱門文章
PTT數位生活區 即時熱門文章