从另一个构造函数调用默认构造函数

Calling the default constructor from another constructor

我试图让重载构造函数调用默认构造函数,但它只给我垃圾编号。我想让它做的是识别输入的日期是否无效,因此将其默认为 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 ();
}

只能在对象首次构造 时调用构造函数。它不是通用功能。

此处的代码正在执行此操作 - 构建一个新的 Date,但未对它执行任何操作。

Date ();

您可以通过 分配 新的默认构造的 Date

来实现您想要的效果
*this = Date(); 

编辑:确保 valid 是您想要的。

首先,在

Date ();

你正在构建一个临时的,然后丢弃它。 C++ 确实具有在现有存储上调用构造函数的低级工具,但普通的构造函数调用只会创建一个新对象。

另请注意

if (valid == false)

可以而且应该更清楚地表达为

if( not valid )

或者如果您喜欢符号运算符,

if( !valid )

现在可以表达原代码的意图

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

  • 默认-先构造后修改,或者

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

这些是从最干净到最不干净的顺序。

请注意,按照另一个答案中的建议,分配一个默认构造的实例,即上面最脏的选项,并且什么都不做,会将 valid 成员设置为 true,从而删除关于构造函数参数无效这一事实的所有信息……

不过,none个选项都不错!就意图而言,将参数错误视为对默认值的请求本身是非常不好的。相反,当您检测到参数错误时,抛出异常或终止,以便客户端代码手头不会有可能意外的对象。

例如,做

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