首先,在
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