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

时间:2015-02-08 04:13:14

标签: c++ constructor call

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

2 个答案:

答案 0 :(得分:1)

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

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

Date ();

您可以通过分配新的默认构造Date来实现您想要的目标。

*this = Date(); 

编辑:请确保在这种情况下valid是您想要的。

答案 1 :(得分:1)

首先,在

Date ();

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

另请注意

if (valid == false)

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

if( not valid )

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

if( !valid )

现在,可以表达原始代码的 intent

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

  • 默认情况下首先构建然后修改,或

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

这些是最清洁到最不洁净的顺序。

请注意,分配默认构造的实例,上面最脏的选项,并且不做任何其他操作,如另一个答案所示,将valid成员设置为true,从而删除所有信息关于构造函数参数无效的事实......

然而,这些选项都不是好的!对于意图,将参数错误视为默认请求的意图本身就是非常糟糕的。相反,当您检测到参数错误时,抛出异常或终止,以便客户端代码不会出现可能意外的对象。

,例如,

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

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

顺便说一下,使用Visual C ++ force-include <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" );
    }
}