如何更改默认构造函数的参数?

Posted

技术标签:

【中文标题】如何更改默认构造函数的参数?【英文标题】:How can I change the parameters of a default constructor? 【发布时间】:2020-09-09 16:33:00 【问题描述】:

我有一个名为Date 的类来控制日期。

我有一个构造函数Date()。如果此构造函数未初始化,则默认日期将由名为 default_ 的私有静态数据成员代替。

我已经在Date.cpp中初始化了default_,如下:

Date Date::default_1, Month::January, 1900;

其中第一个参数是 int 代表当天,第二个参数是 enum class Month 代表月份,第三个是 int 代表年份。

当我运行这个程序时,我可以打印日期,它会显示由default_ 设置的正确默认日期。

问题:

我希望能够使用函数更改默认日期:

setDefaultDate(int day, Month month, int year)

我该怎么做?我尝试如下实现setDefaultDate(),但它不起作用:

void Date::setDefaultDate(int day, Month month, int year)

    default_ = day,month,year;

代码:

日期.h:

#ifndef DATE_H
#define DATE_H
// date.h
// class Date declaration

#include <cassert>
#include <iostream>
using namespace std;

enum class Month

   January = 1,
   February,
   March,
   April,
   May,
   June,
   July,
   August,
   September,
   October,
   November,
   December
;

class Date

public:
   // return the day of the month
   int   day () const;
   // return the month of the year
   Month month () const;
   // return the year
   int year () const;

Date();
   static void setDefaultDate(int day, Month month, int year);

private:

   int   day_;
   Month month_;
   int   year_;

   static Date default_;
;

// standalone function for printing the date
void printDate(const Date& date);

#endif

日期.cpp:

// date.cpp
// Implementation of the Date class

#include "date.h"

int Date::day() const

   return day_;


Month Date::month() const

   return month_;


int Date::year() const

   return year_;


// Note, this standalone function is not part of the Date class
void printDate(const Date& date)

   cout << date.day() << "/"
       // cast to an integer to allow the month to be sent to the stream
<< static_cast<int>(date.month()) << "/"
       << date.year()
       << endl;


Date Date::default_1, Month::January, 1900;

void Date::setDefaultDate(int day, Month month, int year)

   default_ = day,month,year;


Date::Date()

   day_ = default_.day();
   month_ = default_.month();
   year_ = default_.year();

示例

int main()

    auto date_1 = Date;
    date_1.setDefaultDate(29, Month::September, 2020);

    printDate(date_1);

预期输出: 2020 年 9 月 29 日

实际输出: 1900 年 1 月 1 日

它可以编译,但是setDefaultDate() 函数不起作用,并且正在输出default_ 中声明的默认日期。

【问题讨论】:

“它不工作:” 是没有问题的描述。请添加更多细节。此外,您的标题有点误导,因为默认构造函数不接受您可以更改的任何参数。 你没有三参数构造函数(添加Date::Date(int day, Month month, int year) “如果此构造函数未初始化,默认日期将由名为 'default_' 的私有静态数据成员放置在其位置” 为什么?只需初始化构造函数中的成员。不需要这个default_ 变量。 你说的代码为我编译了does not compile,因为缺少默认日期初始化的构造函数。 setDefaultDate 还没进图呢。 @John 那么请澄清 what 不起作用。最好的方法是minimal reproducible example,它准确地重现您现在遇到的错误。 【参考方案1】:

让我们逐行浏览您的main

auto date_1 = Date;

这会做什么?它将调用Date::Date,它将从default_ 读取所有值到date_1。此时default_1/1/1900date_1 现在是一样的。那么

date_1.setDefaultDate(29, Month::September, 2020);

将仅更改 default_default_。我不确定您为什么期望 date_1 在这里更改,可能是因为您将其称为非静态成员函数?您可能打算更改默认日期 before 从中读取。你可以这样做:

int main()

    // call it like static function
    Date::setDefaultDate(29, Month::September, 2020);

    // Only then read from it.
    auto date_1 = Date;
    
    // prints 29/9/2020
    printDate(date_1); 

【讨论】:

【参考方案2】:

您的setDefaultDate() 方法设置default_ 的值,main() 在为date_1 对象调用Date() 构造函数时已经复制了该值。之后更改default_ 的值对date_1 的值没有任何影响。当你打印date_1 时,你输出它初始化的值。更改default_ 的值只会影响后续您之后创建的Date 对象。

如果你想改变date_1的值,你需要:

    致电setDefaultDate()之前致电Date():
int main()

    Date::setDefaultDate(29, Month::September, 2020);
    Date date_1;
    printDate(date_1); // 29/9/2020

    添加非静态方法来改变Date 对象的值。您还应该添加一个可以将用户指定的日期作为输入的非默认构造函数,例如:
class Date

public:
   Date();
   Date(int initialDay, Month initialMonth, int initialYear);

   ...

   void setDay (int newValue);
   void setMonth (Month newValue);
   void setYear (int newValue);

   ...
;
Date::Date() :
   Date(default_.day_, default_.month_, default_.year_)



Date::Date(int initialDay, Month initialMonth, int initialYear) :
   day_(initialDay),
   month_(initialMonth),
   year_(initialYear)



void Date::setDay (int newValue)

   day_ = newValue;


void Date::setMonth (Month newValue)

   month_ = newValue;


void Date::setYear (int newValue)

   year_ = newValue;


...
int main()

    Date date_1;
    printDate(date_1); // 1/1/1900

    date_1.setDay(29);
    date_1.setMonth(Month::September);
    date_1.setYear(2020);
    printDate(date_1); // 29/9/2020

    date_1 = Date(9, Month::September, 2020);
    printDate(date_1); // 9/9/2020

    Date date_2(31, Month::December, 2020);
    printDate(date_2); // 31/12/2020

    Date::setDefaultDate(1, Month::April, 2020);

    Date date_3;
    printDate(date_3); // 1/4/2020

【讨论】:

【参考方案3】:

如果我理解正确,我将向您展示您的代码的修改版本,该版本应该可以满足您的需求。为了使用单个文件,我稍微更改了您的代码

java 不是 C++,C++ 不是 java。而static C++ 中的东西不是 java 的方式。也许你已经习惯了。

在 C++ 中,您可以将默认运行代码设置为 main() 之外 和类之外

...
; // class Date

int Date::default_day = 1;
int Date::default_month = 1;
int Date::default_year = 1900;

void printDate(const Date& date);
void setDefaultDate(int, int, int);

int main(void)

...

所以你已经加载了第一组默认值。

如果你在 main() 内执行它,它会编译,但链接器会 抱怨他们三个都没有解决。

对于setDefaultDate(),您可以将其声明为日期的friend
    friend void setDefaultDate(int, int, int);
PrintDate() 的一种方便且常见的替代方法是将另一个 friend 声明为 Date,如下所示
    friend ostream& operator<<(ostream&, Date&);

使用您的代码的示例

节目展示


just a date at start (should use defaults 1900,1,1)

printDate()
 d: 1 m: 1 y: 1900

Now sets default to 1901/3/2

printDate()
 d: 2 m: 3 y: 1901

Now declared new Date instance as d3(2019,8,7)

printDate()
 d: 7 m: 8 y: 2019

Now print all 3 dates using "<<" operator, redefined for Date class

printDate using insertion operator '<<'
        year is 1900 month is 1 year is 1900

printDate using insertion operator '<<'
        year is 1901 month is 3 year is 1901

printDate using insertion operator '<<'
        year is 2019 month is 8 year is 2019

main()

int main(void)

    cout << "\njust a date at start (should use defaults 1900,1,1)\n";
    Date d1;
    printDate(d1);
    cout << "\nNow sets default to 1901/3/2\n";
    setDefaultDate(2, 3, 1901);
    Date d2;
    printDate(d2);
    cout << "\nNow declared new Date instance as d3(2019,8,7)\n";
    Date d3(2019, 8, 7);
    printDate(d3);
    cout << "\nNow print all 3 dates using \"<<\" operator, redefined for Date class\n";
    cout << d1 << d2;
    cout << d3;
    return 0;

代码使用printDate() 和重载的&lt;&lt; 作为printDate() 的替代品。我为 3 个 Date 留下了两个 cout,只是为了表明您可以像使用任何其他 cout 调用一样链接打印。 程序设置默认值beforeinsidemain() 我添加了第二个构造函数,它接受 daymonthyear 作为参数

完整的例子

#include <iostream>
using namespace std;

class Date

private:
    int  year_;
    int  month_;
    int  day_;

public:
    int year()  const  return year_;  ;
    int month() const  return month_; ;
    int day()   const  return day_;   ;

    // default as Date d;
    Date() : 
        year_(default_year), month_(default_month), day_(default_day) ;
    // as Date d(2020,9,8)
    Date(int y, int m, int d) :
        year_(y), month_(m), day_(d);

    friend void setDefaultDate(int, int, int);
    friend ostream& operator<<(ostream&, Date&);

private:
    static int  default_year;
    static int  default_month;
    static int  default_day;

; // class Date

int Date::default_day = 1;
int Date::default_month = 1;
int Date::default_year = 1900;

void printDate(const Date& date);
void setDefaultDate(int, int, int);

int main(void)

    cout << "\njust a date at start (should use defaults 1900,1,1)\n";
    Date d1;
    printDate(d1);
    cout << "\nNow sets default to 1901/3/2\n";
    setDefaultDate(2, 3, 1901);
    Date d2;
    printDate(d2);
    cout << "\nNow declared new Date instance as d3(2019,8,7)\n";
    Date d3(2019, 8, 7);
    printDate(d3);
    cout << "\nNow print all 3 dates using \"<<\" operator, redefined for Date class\n";
    cout << d1 << d2;
    cout << d3;
    return 0;



void printDate(const Date& date)

    cout << "\nprintDate()\n" <<
        " d: " << date.day() <<
        " m: " << date.month() <<
        " y: " << date.year()
        << endl;
;

void setDefaultDate(int day, int month, int year)

    Date::default_day = day;
    Date::default_month = month;
    Date::default_year = year;
;

ostream& operator<<(ostream& out, Date& date)

    cout << "\nprintDate using insertion operator '<<'\n" <<
        "\tyear is " << date.year_ <<
        " month is " << date.month_ <<
        " year is " << date.year_ <<
        endl;
    return out;
;

这里没有宗教。我是在 MSVC 19.27

下编译的

【讨论】:

以上是关于如何更改默认构造函数的参数?的主要内容,如果未能解决你的问题,请参考以下文章

如何更改 C# Record 构造函数的行为

如何将构造函数参数传递给 AppDomain.CreateInstanceXXX?

如何将 std::map 作为默认构造函数参数传递

c++构造函数默认参数

pyyaml 中的默认构造函数参数

JSON.net:如何在不使用默认构造函数的情况下反序列化?