unmatching in default constructor of Year

Hello all,

This code is from Programming Principles and Practice using C++ by stroustrup:

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

#include "C:\Users\CS\Desktop\Documents\std_lib_facilities.h"
#include <conio.h>

//**************************************************************

class Year {
	static const int min = 1800;
	static const int max = 2200;
public:
	Year(int x): y(x) { if(x < min || x > max) error("bad year");}
	int year() {return y;}
private:
	int y;
};

//*************************************************

class Date { 
public:
	enum Month {
		jan = 1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec
	};
	Date(Year yy, Month mm, int dd) {
	 if((mm < 1 || mm > 12 || dd < 1 || dd > 31)
		|| (yy.year() % 4 != 0 && mm == 2 && dd > 28)
		  || ( (mm == 4 || mm == 6 || mm == 9 || mm == 11) && 
				( dd > 30)))
				error("invalid date!");
	else m = mm; d = dd; y = yy;
   }
 int month() { return m; }
 int day()   { return d; }
 int year()  { return y.year();}
private:
 int d;
 Month m;
 Year y;
};

//**************************************************************

ostream& operator<<(ostream& os, Date& dd)
{
	return os << '(' << dd.year() << ',' << dd.month() << ',' << dd.day() << ')';
}

//**********************************************

int main()
try {
	Date d1 (Year(1983), Date:: mar, 25);
	Date d2 = d1;
	cout << d1 << ' ' << d2 << endl;
	getch();
	return 0;
}
catch(exception& e)
{
	cerr << e.what() << endl;
	getch();
	return 0;
}


In this code Date d1(Year(1983), Date::mar, 25) we have made an object. First argument will be sent to default Date constructor, which is Date(Year y, Month m, int d) while this Year y does not match to Year default constructor because that is Year(int) that means that every Year object should has an int argument on making time and Year y does not offer any argument for y. I think it’s an unmatching program, page 321 that makes bother to solve the drill version 4 page 333.

If my above comment is right, so how to solve these errors:

1
2
Error 1 error C2512: 'Year' : no appropriate default constructor
Error 2	IntelliSense: no default constructor exists for class "Year"		

?

Thank you.
Class Date has member of type Year that is Year y. When the constructor of Date is called it invokes constructors of its members in particularly a constructor of member y. And as you did not specify explicitly what constructor for y will be called the compiler calls the default constructor that is absent in class Year. You could write for example

Date(Year yy, Month mm, int dd) : y( yy ) {
// other statements
Thank you for your reply. It worked.
But, first,I think I have specified the constructor for y that is:
 
Year(int x): y(x) { if(x < min || x > max) error("bad year");}

If the date invokes its members constructors it should invoke that constructor for Year y. And it is default constructor that is presence.

Second, why that constructor is not explicit?
Where is the default constructor of class Year present?
The class has only one constructor with one parameter if do not take into account the implicit copy constructor. It has no default constructor.
Last edited on
OK, I just now found that the default constructor has no argument. So, that one which I defined is constructor but not the default one.
Now every thing is OK except one:
In this part of code :
1
2
3
4
5
6
7
8
Date(Year yy, Month mm, int dd) {
	 if((mm < 1 || mm > 12 || dd < 1 || dd > 31)
		|| (yy.year() % 4 != 0 && mm == 2 && dd > 28)
		  || ( (mm == 4 || mm == 6 || mm == 9 || mm == 11) && 
				( dd > 30)))
				error("invalid date!");
	else m = mm; d = dd; y = yy;
   }


I assigned yy to y by y = yy statement and again I get that errors while by yours y(yy), the errors vanish. Aren't those two statements, y = yy and y(yy) equal?
If you did not define the default constructor then error will not vanish. As I wrote early when the constructor of class Date is called it in turn calls constructors for each its members. In example I showed the constructor of class Year with one parameter is called explicitly so there is no need in the default constructor.

By the way maybe you meant

else { m = mm; d = dd; y = yy; }

instead of

else m = mm; d = dd; y = yy;
Last edited on
Now from the whole of the code, our issue is only about the difference(s) between
1
2
 Date(Year yy, Month mm, int dd) : y( yy ) {
// other statements 
and
1
2
3
Date(Year yy, Month mm, int dd) {
// other statements
else {m = mm; d = dd; y = yy;}
.
In this code there is no difference between those two else, and both cause to error even your else { m = mm; d = dd; y = yy;}
I have understood nothing. I think I exaplained already what is the problem. So it is not clear why you are asking your question ahain and again. And I do not see "two else"
If you got an error then report what error you got.
I said if we use else{m = mm; d = dd; y = yy;} instead of else m = mm; d = dd; y = yy; the previous errors still again exist, as following:
1
2
3
Error 1 error C2512: 'Year' : no appropriate default constructor
Error 2	IntelliSense: no default constructor exists for class "Year"		
 
I already explained about the default constructor. Why are you asking the question again?!

In this code snip

Date(Year yy, Month mm, int dd) : y( yy ) {

the implicit copy constructor is called explicitly. So member y of class Date will be created with using this copy constructor.

In this code snip

Date(Year yy, Month mm, int dd) {

the compiler will try to call the default constructor for member y that does not exist. So the compiler issues the error.
Last edited on
I think I can't say you the problem clearly or you can't say the answer to me clearly!
You solved the main part of my problem but not all of that. But anyway, I thank you very much and try to figure out that last issue in some another way.
thank you again.
Maybe I can try and clarify this:

At line 53 when you instaniate Date d1, the compiler initializes all members of the class. The compiler does this by calling the constructor of each member.
Line 38 will cause the default constructor of Year to be called, but as Vlad has explained, you don't have a default constructor for Year and have not provided an explicit initialization of y in your Date constructor.

Vlad's code
 
Date(Year yy, Month mm, int dd) : y( yy ) 

provides a way to initialize Year::y. This must be done before any code in your Date constructor is executed. It is irrelevant if the code in your Date contructor (between the braces) sets y.

An alternative would be to alter your constructor for Year.
1
2
3
4
5
6
class Year 
{
public:
    Year(int x=2013): y(x)
    {  /* your existing logic */ } 
...

This way, if Year is instantiated, the compiler can call the constructor since a default value is provided.

Does this help?

Last edited on
Dear vlad from moscow,

Your last comment was great and exactly was what I wanted! Thank you for coming back again to issue and picking last one!

thank you dear AbstractionAnon for your explanation.
The case was about calling the copy constructor and default constructor. And is finished.
thank you again.

Topic archived. No new replies allowed.