PhiloRobotist
PhiloRobotist

Reputation: 337

Modify data member of base class from constructor of derived class in C++

I can't understand the output of this code. I expect 10 to be printed, but the output is 85. Can someone explain what's happening?

#include <iostream>
using namespace std;
class A
{  
    public:   
        int x=3;
        A(int a) : x(a) {}
};

class B: public A
{   
    public:  
        int y = 10;
        B() : A(y) {}
};

int main()
{
    B b;    
    cout << b.x << endl;
    return 0;
}

But, changing it to:

class B: public A
{   
    public:  
        int y = 10;
        B(int s) : A(s) {}
};

int main()
{
    B b(4); 
    cout << b.x << endl;
    return 0;
}

It works as expected (prints 4).

Upvotes: 7

Views: 1492

Answers (3)

PhiloRobotist
PhiloRobotist

Reputation: 337

As suggested by the link in @Someprogrammerdude's comment:

The order of member initializers in the list is irrelevant: the actual order of initialization is as follows:

  1. If the constructor is for the most-derived class, virtual bases are initialized in the order in which they appear in depth-first left-to-right traversal of the base class declarations (left-to-right refers to the appearance in base-specifier lists)
  2. Then, direct bases are initialized in left-to-right order as they appear in this class's base-specifier list
  3. Then, non-static data member are initialized in order of declaration in the class definition.
  4. Finally, the body of the constructor is executed

Upvotes: 0

Fairyteller
Fairyteller

Reputation: 312

Because of initialization order rules in first case you call A() constructor before y was assigned to 10, so value of y is undefined and depends on current value of those sizeof(int) bytes in the stack. So you initialize x with that undefined semi-random value and print it later. In second case you call B(int) with s = 4 and it successfully initializes x with 4.

Upvotes: 2

Sam Varshavchik
Sam Varshavchik

Reputation: 118340

This is called "undefined behavior".

Base classes are constructed first, before the class members are constructed.

In this case, you're passing the contents of an uninitialized class member to the base class's constructor.

Just because you have an initialization statement for the class member that appears on a previous line, in the .cpp file, doesn't mean that this is the initialization order. C++ does not always work this way. You're passing an uninitialized y to the base class's constructor, and then when the base class returns the subclass gets constructed, setting y to what it's initialized to.

Upvotes: 6

Related Questions