I have troubles understanding the output of the following code when it comes to the first printed number.
#include <iostream>
#include <string>
using namespace std;
class A{
public:
int x;
A(){
x = 5;
}
};
class B: public A{
public:
static int x;
B(){
x ;
}
B(int i){
x = x i;
}
B(string s){
x--;
}
};
int B::x=10;
int main()
{
B b1;
B b2(2008);
B b3("Random string");
cout << b1.x << " : " << b2.x << " : " << b3.x << endl;
return 0;
}
output (the first "2018" is the one I'm having troubles with)
2018 : 2018 : 2018
CodePudding user response:
The first thing to note is that A::x
is different from B::x
. B
does inherit A::x
, but it introduces a new B::x
which is static
. Hence x
in the scope of B
refers to B::x
(not to A::x
). Ergo, you can remove the base class without changing the output:
#include <iostream>
#include <string>
using namespace std;
class B {
public:
static int x;
B(){
x ;
}
B(int i){
x = x i;
}
B(string s){
x--;
}
};
int B::x=10;
int main()
{
B b1;
B b2(2008);
B b3("Random string");
cout << b1.x << " : " << b2.x << " : " << b3.x << endl;
}
2018 : 2018 : 2018
Now, B::x
starts out as 10
because thats what you initialize it to. Then B b1;
increments it (in the default constructor), then B b2(2008);
adds 2008
to B::x
, it is 2019
now. Eventually B b3("Random string");
decrements it to arrive at the value 2018
. Because B::x
is static you see 3 times the same output.
The confusion seems to be caused by B::x
being a static member and A::x
being hidden by B::x
. To reiterate the above: static int x;
declares x
to be a static member. There is only 1 for all instances. When one instance increments it then any other instance will see the incremented value as well. B::x
hides A::x
because they have the same name. I suppose this is not intentional. If your intention was to let B
inherit x
from B
and use that, then you should remvoe the delcaration and definition of B::x
.
It's not that I don't understand a static variable, it's more like me not getting why b1 that (seemingly) call b(),outputs 2018 instead of incrementing the static x to 11
The line B b1;
does increment A::x
from 10
to 11
. Though the constructor does not produce any output. The values are only printed after all constructors finished.
CodePudding user response:
Your static data member x
inside the derived class B
hides the nonstatic data member x from base class A
since they both have the same name. The explanation of the output is given below.
Case 1
Here we consider the statement:
B b1;
The above statement has the following effects:
- It calls the default constructor
B()
of classB
. - Then the default constructor
A()
of class A is implicitly called. This sets the non-static data memberx
of the subobject to5
. - Finally, the body of the default constructor
B()
is executed. Due to thisx ;
is evaluated and sox
now is11
. This is because the non-static data memberx
from base classA
is hidden by the static data memberx
of derived classB
. Sox ;
increments the static data member(which was10
) instead of the nonstatic data member from baseA
.
Case 2
Here we consider the statement:
B b2(2008);
The above statement has the following effect:
- The parameterized ctor
B(int)
of classB
is called. - Then the default ctor
A()
of classA
is implicitly called. This sets the non-static data memberx
of the subobject to5
. - Finally, the body of the parameterized ctor
B(int)
is executed. Due to thisx = x i;
is evaluated and so the static data memberx
becomes2019
(since x was11
andi
is2010
). This is because the non-static data memberx
from base classA
is hidden by the static data memberx
of derived classB
. Sox = x i;
uses the static data member(which was11
) instead of the non-static data member from baseA
.
Case 3
Here we consider the statement:
B b3("Random string");
The above statement has following effects:
- The parameterized ctor
B(std::string)
of classB
is called. - Then the default ctor
A
of classA
is implicitly called. This sets the non-static data memberx
of the subobject to5
. - Finally, the body of the parameterized ctor
B(std::string)
is executed. Due to thisx--;
is evaluated and so nowx
contains2018
. This is because the non-static data memberx
from base classA
is hidden by the static data memberx
of derived classB
. Sox--;
decrements the static data member(which was2019
) instead of the non-static data member from baseA
.
So now the static data member x
has the value 2018
.
Case 4
Here we consider the statement:
cout << b1.x << " : " << b2.x << " : " << b3.x << endl;
The above statement uses the static data member x
values because the non-static data member x
is hidden. And since the static data member x
has the value 2018
you get the output you mentioned.