首先,在
Date();
你正在建設一個臨時的,並丟棄它。 C++確實有低層次的設施來調用現有存儲上的構造函數,但普通的構造函數調用只是創建一個新對象。
還要注意的是
if (valid == false)
可以而且應該更加清潔表述爲剛剛
if(not valid)
,或者如果你喜歡象徵性的運營商,
if(!valid)
現在,意圖的原始代碼可以表示爲
這些是爲了最乾淨的大多數不潔。
請注意,分配默認構造的情況下,上述最髒的選項,並做而已,在另一個答案建議,將valid
成員設置爲true
,從而消除對事實的所有信息,構造函數參數無效…
但是,這些選項都不是好的!對於意圖來說,將參數錯誤當作默認請求來處理,本身就非常不合適。相反,當您檢測到參數錯誤時,拋出異常或終止,以便客戶端代碼不會有可能意外的對象。
例如,做
if(not valid) { throw std::runtime_error("Date::<init>: invalid args"); }
有些人喜歡使用std::logic_error
或std::range_error
。
順帶一提,用Visual C++力包括<iso646.h>
得到支撐的C++的關鍵字(以下不精確,保留字)and
,or
和not
。 (不推薦,但至少髒原意實現!)的
實施例共同的構造的方法:每個構造確保有效目標的
class Date
{
private:
int day_;
int month_;
int year_;
string month_name_;
bool is_valid_;
Date(int month, int day, int year, const string& month_name);
public:
static
auto month_name_for(int month, int day, int year)
-> string;
Date();
Date(int month, int day, int year);
};
Date::Date(const int m, const int d, const int y, const string& month_name)
: month_( month_name == ""? 1 : m)
, day_( month_name == ""? 1 : d)
, year_( month_name == ""? 2000 : y)
, month_name_( month_name == ""? "Jan" : month_name)
, is_valid_(month_name != "")
{}
auto Date::month_name_for(const int m, const int d, const int y)
-> string
{
if(y > 0)
{
if(m == 1 && 1 <= d && d <= 31) { return "Jan "; }
const int days_in_feb = 28; // TODO: correct for leap year
if(m == 2 && 1 <= d && d <= days_in_feb) { return "Feb "; }
if(m == 3 && 1 <= d && d <= 31) { return "Mar "; }
//etc.
}
return "";
}
Date::Date()
: Date(0, 0, 0, "")
{}
Date::Date(const int m, const int d, const int y)
: Date(m, d, y, month_name_for(m, d, y))
{}
實施例(推薦):
class Date
{
private:
int day_;
int month_;
int year_;
public:
static
auto month_name_for(int month)
-> string;
static
auto is_valid(int month, int day, int year)
-> bool;
Date();
Date(int month, int day, int year);
};
auto Date::month_name_for(const int m)
-> string
{
static const string names[] = { "Jan", "Feb" }; // Etc.
return (1 <= m && m <= 12? names[m-1] : "");
}
auto Date::is_valid(const int m, const int d, const int y)
-> bool
{
if(y > 0)
{
if(m == 1 && 1 <= d && d <= 31) { return true; }
const int days_in_feb = 28; // TODO: correct for leap year
if(m == 2 && 1 <= d && d <= days_in_feb) { return true; }
if(m == 3 && 1 <= d && d <= 31) { return true; }
//etc.
}
return false;
}
Date::Date()
: Date(1, 1, 2000)
{}
Date::Date(const int m, const int d, const int y)
: month_(m), day_(d), year_(y)
{
if(not is_valid(m, d, y))
{
throw runtime_error("Date::<init>: invalid arguments");
}
}
你是我的英雄,我愛你。 – JMoore 2015-02-08 04:18:09
Downvote因爲(a)這個答案設法將一個成員初始化爲錯誤的值,並且(b)它使用了所有可能的非非自然方法中最少的清理來完成它。 – 2015-02-08 05:17:37
@ Cheersandhth.-Alf(a)我不夠聰明,不知道會是什麼成員。我誠實地嘗試。 (b)我會說這是非常不乾淨的,也是* working *的最短路徑。它不是*「最不乾淨」*,但我不會用例子來痛苦你,我敢肯定,你並沒有對這種直覺感到失望。 – 2015-02-08 19:20:03