The detail is a little bit long to formulate, and I have broken down the problem I'm facing into 3 "rounds", so bear with me...
For the first round, consider the following C code, which is error-free and one that behaves as expected:
#include <iostream>
using namespace std;
class rect{
float width;
float length;
public:
rect( float w = 5, float l=8 ) : width(w), length(l) {}
float area(){return width * length;}
};
class box{
rect base;
float height;
public:
box(rect a={2,7}, float c=9) : base(a), height(c){ } //round 1
//box(rect a={2}, float c=9) : base(a), height(c){ } //round 2 option 1
//box(rect a=(2), float c=9) : base(a), height(c){ } //round 2 option 2
//box(rect a=(2,7), float c=9) : base(a), height(c){ } //round 3
float volume(){return base.area() * height;}
};
int main(){
rect a;
cout<<"Area a= "<<a.area()<<endl;
rect b(3,4);
cout<<"Area b= "<<b.area()<<endl;
rect c(3);
cout<<"Area c= "<<c.area()<<endl;
box d(a,6);
cout<<"Volume d= "<<d.volume()<<endl;
box e(a);
cout<<"Volume e= "<<e.volume()<<endl;
box f;
cout<<"Volume f= "<<f.volume()<<endl;
return 0;
}
When I run the code, it outputs:
Area a= 40
Area b= 12
Area c= 24
Volume d= 240
Volume e= 360
Volume f= 126
Analyzing the result:
Area a= 40since width ofais set to 5 and length ofais set to 8 by the default constructorArea b= 12since width ofbis set to 3 and length ofbis set to 4 from the argumentsArea c= 24since width ofcis set to3from the argument, and since argument for length ofcis missing, it is set to8from the default constructor value for length in classrectVolume d= 240since rectais5 x 6from default constructor in classrect, and height of boxdis 6 from argumentVolume e= 360since rectais5 x 6from default constructor in classrect, and height of boxeis 9 from default constructor in classboxVolume f= 126outputs 126 since rect offis2 x 7from default constructor in classbox, and height of boxeis 9 from default constructor in classbox
Next, for round 2, replace the box class constructor line by round 2 option 1:
box(rect a={2}, float c=9) : base(a), height(c){ }
Or by option 2:
box(rect a=(2), float c=9) : base(a), height(c){ }
Note the change from curly brace in rect a={2} to normal braces rect a=(2)
Now, running the above code, both constructor declarations (rect a={2} and rect a=(2)) will give the following output:
Area a= 40 //same logic as in round 1
Area b= 12 //same logic as in round 1
Area c= 24 //same logic as in round 1
Volume d= 240 //same logic as in round 1
Volume e= 360 //same logic as in round 1
Volume f= 126 //output changed because width for rect of f is 2 from default constructor in class box
// since length default value in class a is missing, length for rect of f is set to 8 from default constructor in class rect
// height of box e is 9 from default constructor in class box
Note for round 2, the code gives the same output in both constructor declarations options 1 and 2 (rect a={2} & rect a=(2)).
So far, everything is working as it should.
Next, for the final and mayhem round, replace the box class constructor by option 3:
box(rect a=(2,7), float c=9) : base(a), height(c){ }
Note the normal braces in rect a=(2,7).
Every other result stays the same (because they are not affected by the change) except for Volume f, which is a whopping 504. By my observation, the compiler has chosen:
- width 7, from
rect a=(2,7) - length 8 from default width in
rectclass - height 9 from default height from
boxclass itself
The choice for height is logical, but the choice for width and length is confusing.
Can anybody explain the mechanics behind this?
My expectation was, round 3 should behave exactly as round 1, since round 2 option 1 & round 2 option 2 are behaving the same.
My question in summary is, what brought about the difference declaring a constructor for a class containing another class member as round 1 curly braces and as round 3 normal braces?
CodePudding user response:
rect a={2,7} will invoke the rect constructor with two input values, w=2 and l=7.
rect a=(2,7) will first invoke the comma operator (which in this case will return 7), and then will invoke the rect constructor with one input value, w=7, leaving the l parameter to use its default value.
