首先,在
Date ();
你正在构建一个临时的,并丢弃它。 C++ 确实具有在现有存储上调用构造函数的低级工具,但普通的构造函数调用只会创建一个新对象。
还要注意
if (valid == false)
可以而且应该更简洁地表达为just
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" );
}
}