2015-02-08 255 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"); 
    } 
}