0

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.

2
  • 3
    First idea would be that you are not setting this->x, but only x, and therefore this->x is never initialized. Can you confirm? Commented Jun 3, 2015 at 7:23
  • 2
    I'm not sure but could it be that your "check" if x has been set is wrong? if(!setX(x)) behaves differently depending on the value of x, which has not been initialized. So technically it can any value. If your lucky it's 0, in which case your code works, but that doesn't have to be. Commented Jun 3, 2015 at 7:25

2 Answers 2

5

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;
Sign up to request clarification or add additional context in comments.

1 Comment

That was it. So foolish.
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.