Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

c++14

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).

like image 489
PhiloRobotist Avatar asked Apr 15 '21 11:04

PhiloRobotist


2 Answers

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.

like image 163
Sam Varshavchik Avatar answered Oct 23 '22 14:10

Sam Varshavchik


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.

like image 42
Fairyteller Avatar answered Oct 23 '22 14:10

Fairyteller