1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | // Code derived from Stroustrup's PPP2 book
// § 9.7.3 Default constructors
// -and beginning on p 329
#include <iostream>
#include <stdexcept>
#include <vector>
using namespace std;
void error(const char* s) { throw runtime_error(s); }
enum class Month {
jan = 1,
feb,
mar,
apr,
may,
jun,
jul,
aug,
sep,
oct,
nov,
dec
};
//------------------------------------------------------------------------------
class Date; // pair of fwd decls (used in Date's default ctor)
const Date& default_date(); //
//------------------------------------------------------------------------------
// Instead of placing the default values for members in the constructor, we
// could place them on the [private] members themselves
class Date {
public:
Date(); // default constructor
Date(int year, Month month, int day);
Date(int y); // January 1 of year y
class Invalid {}; // to be used as a Date exception
// . . .
int year() const { return y; }
Month month() const { return m; }
int day() const { return d; }
friend ostream& operator<<(ostream& os, const Date& d)
{
return os << '{' << d.y << ',' << int(d.m) << ',' << d.d << '}';
}
private:
bool is_valid(); // return true if date is valid
int y{2001};
Month m{Month::jan};
int d{1};
};
// given default_date(), it is trivial to define a default constructor for Date
Date::Date()
: y{default_date().year()},
m{default_date().month()},
d{default_date().day()}
{
}
Date::Date(int year, Month month, int day) : y{year}, m{month}, d{day} {}
// January 1 of year yy
Date::Date(int yy) : y{yy}
{
if (! is_valid())
throw Invalid{}; // check for validity
}
// return true if date is valid
bool Date::is_valid()
{
if (int(m) < 1 || 12 < int(m))
return false;
// ...
return true; // naive
}
//------------------------------------------------------------------------------
// The first day of the 21st century (value is already checked, by definition)
const Date& default_date()
{
static Date dd{2001, Month::jan, 1};
return dd;
}
int main()
{
// ten elements with the default Date value, Date{} (the default constructor)
vector<Date> birthdays(10);
for (auto& birthday : birthdays)
cout << birthday << '\n';
{
// Without the default constructor, we would have had to be explicit
vector<Date> birthdays(10, default_date()); // ten default Dates
// ten default Dates
vector<Date> birthdays2 = {default_date(), default_date(), default_date(),
default_date(), default_date(), default_date(),
default_date(), default_date(), default_date(),
default_date()};
}
}
|
build & run:
g++ -std=c++20 -O2 -Wall -pedantic ./ch_09/main_p329.cpp && ./a.out