Reputation: 21
I have a class called Date
that controls the date.
I have a constructor Date()
. If this constructor is uninitialized, a default date will be put in its place by a private, static data member called default_
.
I have initialized default_
in Date.cpp
as follows:
Date Date::default_{1, Month::January, 1900};
Where the first argument is an int
for the day, second is an enum class
called Month
for the month, and third is an int
for the year.
When I run this program, I can print the date and it shows the correct default date that has been set by default_
.
I want to be able to change the default date with a function:
setDefaultDate(int day, Month month, int year)
How can I do this? I have tried to implement setDefaultDate()
as follows but it is not working:
void Date::setDefaultDate(int day, Month month, int year)
{
default_ = {day,month,year};
}
Date.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
Date.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);
}
Expected output:
29/9/2020
Actual Output:
1/1/1900
It compiles, but the setDefaultDate()
function is not working, and the default date is being outputted that was declared in default_
.
Upvotes: 0
Views: 402
Reputation: 1765
I will show you a modified version of your code that should do what you need to, if I understood it correctly. I changed your code a bit, in order to use a single file
java is not C++, C++ is not java. And static
things in C++ goes not the java way. Maybe you are used to that.
One thing is in C++ you can set up the defaults running code just outside of main()
and outside the class as
...
}; // 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)
{
...
And so you have the first set of defaults loaded.
And if you do it inside
main()
it compiles but the linker will complain about all 3 of them as unresolved.
setDefaultDate()
you can just declare it as Date's friend
friend void setDefaultDate(int, int, int);
PrintDate()
is to declare another friend
to Date
, as friend ostream& operator<<(ostream&, Date&);
Program shows
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()
isint 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()
and also the overloaded <<
as an alternative to printDate()
. I left two cout
for the 3 Date
just to show that you can chain the printing as with any other cout
call.main()
day
, month
and year
as arguments#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;
};
No religion here. I compiled it just under MSVC 19.27
Upvotes: 0
Reputation: 597906
Your setDefaultDate()
method sets only the value of default_
, which main()
has already made a copy of when calling the Date()
constructor for the date_1
object. Changing the value of default_
afterwards has no effect whatsoever on the value of date_1
. When you print date_1
, you output the value it was initialized with. Changing the value of default_
will only have an effect on subsequent Date
objects that you create afterwards.
If you want to change the value of date_1
, you need to either:
setDefaultDate()
before calling Date()
:int main()
{
Date::setDefaultDate(29, Month::September, 2020);
Date date_1;
printDate(date_1); // 29/9/2020
}
Date
object. You should also add a non-default constructor that can take a user-specified date as input, eg: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
}
Upvotes: 0
Reputation: 11360
Let's step through your main
line by line:
auto date_1 = Date{};
What will this do? It will call Date::Date
, which will read all of the values from default_
into date_1
. At this point default_
is 1/1/1900
and date_1
now is the same. Then
date_1.setDefaultDate(29, Month::September, 2020);
will change default_
and default_
only. I'm not sure why you expect date_1
to change here, maybe because you've called it like a non-static member function? You probably meant to change the default date before reading from it. You can do it like so:
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);
}
Upvotes: 1