2015-02-08 252 views
0

我想让重载的构造函数调用默认的构造函数,但它只给了我垃圾数。我想要它做的是确认输入的日期是否无效,因此默认为1/1/2000。从另一个构造函数调用默认构造函数

#include <iostream> 
#include <iomanip> 
#include <string> 
#include "date.h" 

using namespace std; 

Date::Date() 
{ 
     month = 1; 
     day = 1; 
     year = 2000; 
     monthName = "Jan "; 
     format = 'D'; 
     valid = true; 
} 

Date::Date (int m, int d, int y) 
{ 
    valid = false; 

     if (y > 0) 
     { 
      //January 
      if (m == 1 && d >= 1 && d <= 31) 
      { 
       month = m; day = d; year = y; 
       monthName = "Jan "; valid = true; 
      } 

      //February 
      else if (m == 2 && d >= 1 && d <= 28) 
      { 
       month = m; day = d; year = y; 
       monthName = "Feb "; valid = true; 
      } 

      //etc. 
     } 

    if (valid == false) 
     Date(); 
} 

回答

1

一个构造当对象是第一次被构造只能被调用。这不是一个通用功能。

你的代码是这样做的 - 构建一个新的Date,但不做任何事情。

Date(); 

你可以达到你想要分配新,默认构造Date什么。

*this = Date(); 

编辑:确保valid是你希望它是在这种情况下什么。

+0

你是我的英雄,我爱你。 – JMoore 2015-02-08 04:18:09

+0

Downvote因为(a)这个答案设法将一个成员初始化为错误的值,并且(b)它使用了所有可能的非非自然方法中最少的清理来完成它。 – 2015-02-08 05:17:37

+0

@ Cheersandhth.-Alf(a)我不够聪明,不知道会是什么成员。我诚实地尝试。 (b)我会说这是非常不干净的,也是* working *的最短路径。它不是*“最不干净”*,但我不会用例子来痛苦你,我敢肯定,你并没有对这种直觉感到失望。 – 2015-02-08 19:20:03

1

首先,在

Date(); 

你正在建设一个临时的,并丢弃它。 C++确实有低层次的设施来调用现有存储上的构造函数,但普通的构造函数调用只是创建一个新对象。

还要注意的是

if (valid == false) 

可以而且应该更加清洁表述为刚刚

if(not valid) 

,或者如果你喜欢象征性的运营商,

if(!valid) 

现在,意图的原始代码可以表示为

  • 通过转发到一个公共的构造(一种自然的方式将是通过调用并通过一个月份名称函数的结果),或

  • 默认-构建第一和然后修改或

  • 通过分配默认构造的实例。

这些是为了最干净的大多数不洁。

请注意,分配默认构造的情况下,上述最脏的选项,并做而已,在另一个答案建议,将valid成员设置为true,从而消除对事实的所有信息,构造函数参数无效&hellip;

但是,这些选项都不是好的!对于意图来说,将参数错误当作默认请求来处理,本身就非常不合适。相反,当您检测到参数错误时,抛出异常或终止,以便客户端代码不会有可能意外的对象。

例如,做

if(not valid) { throw std::runtime_error("Date::<init>: invalid args"); } 

有些人喜欢使用std::logic_errorstd::range_error

顺带一提,用Visual C++力包括<iso646.h>得到支撑的C++的关键字(以下不精确,保留字)andornot。 (不推荐,但至少脏原意实现!)的


实施例共同的构造的方法:每个构造确保有效目标的

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"); 
    } 
}