Reputation: 1041
When I run code that attempts to initialize an array of objects, and one has an invalid value, it doesn't seem to call the constructor, which would set a proper default value. The code below produces the output:
1
2
1528112104
Toy code:
#include <iostream>
using namespace std;
class BeeBoop
{
public:
static const int MIN_X = 1;
static const int MAX_X = 2;
BeeBoop(int x);
int getX() { return x; }
bool setX(int x);
private:
int x;
};
int main()
{
BeeBoop boops[] =
{
BeeBoop(1),
BeeBoop(2),
BeeBoop(3)
};
for (int i = 0; i < 3; i++)
cout << boops[i].getX() << endl;
}
BeeBoop::BeeBoop (int x)
{
if(!setX(x))
x = MIN_X;
}
bool BeeBoop::setX(int x)
{
if (x < MIN_X || x > MAX_X)
return false;
this->x = x;
return true;
}
Why isn't it calling the constructor and setting it to the default for BeeBoop(3)?
Even weirder, if I switch the order of the initialization list to
...
BeeBoop boops[] =
{
BeeBoop(1),
BeeBoop(3),
BeeBoop(2)
)
...
The output becomes:
1
0
2
So it initializes to 0, which is also not the default.
Upvotes: 0
Views: 76
Reputation: 311156
Local variables of a class member function and function parameters are local variables hide data members of the class.
For example in the constructor parameter named x
hides data member x
BeeBoop::BeeBoop (int x)
{
if(!setX(x))
x = MIN_X;
}
Thus in statement
x = MIN_X;
in the left side of the assignment there is used parameter x
.
You should use either
BeeBoop::x = MIN_X;
or
this->x = MIN_X;
All functions where there exist the same problem have to be updated the same way.
Take into account that it is better to declare function getX
with qualofoer const
int getX() const { return x; }
As the constructor of the class does not have specifier explicit
then it is a conversion constructor. it means that you could write simply
BeeBoop boops[] = { 1, 2, 3 };
And function main could be simplified the following way:)
int main()
{
for ( BeeBoop b : { 1, 2, 3 } )
{
std::cout << b.getX() << std::endl;
}
}
The program output will be
1
2
1
Upvotes: 0
Reputation: 213200
You're using the name x
as both a function parameter and as a member variable (probably not a good idea!). Therefore you need to change:
BeeBoop::BeeBoop (int x)
{
if(!setX(x))
x = MIN_X;
}
to:
BeeBoop::BeeBoop (int x)
{
if(!setX(x))
this->x = MIN_X;
}
otherwise you're just modifying the parameter x
rather than setting the member variable. (Alternatively you could just use unique names for parameters and member variables to avoid such ambiguities.)
Note that if you had compiled with suitable warnings enabled (-Wshadow
) the compiler would have been able to point out your mistakes:
main.cpp: In constructor 'BeeBoop::BeeBoop(int)':
main.cpp:30:24: warning: declaration of 'x' shadows a member of 'BeeBoop' [-Wshadow]
BeeBoop::BeeBoop (int x)
^
main.cpp:14:13: note: shadowed declaration is here
int x;
^
main.cpp: In member function 'bool BeeBoop::setX(int)':
main.cpp:36:25: warning: declaration of 'x' shadows a member of 'BeeBoop' [-Wshadow]
bool BeeBoop::setX(int x)
^
main.cpp:14:13: note: shadowed declaration is here
int x;
Upvotes: 5