Megamozg
Megamozg

Reputation: 1063

Initialization of a member when passing parameters to a base class constructor

In the code below i'm assigning a value to uninitialized class member upon creation of a base class. Why didn't this cause runtime error?

class Foo {
public:
    Foo(std::string) {}
};

class Bar : public Foo {
public:
    Bar() : Foo(s = f()) {} // assigning to uninitialized class member

    void print() { 
        std::cout << s << std::endl; 
    }
    std::string f() {
        return "Some string";
    }

private:
    std::string s;
};

int main()
{
    Bar b;
    b.print();
    return 0;
}

But adding another one member to the class Bar produces an error on creation of the Foo class:

Class Bar {

// same as above

private:
    std::string s;
    int a;        // adding another member
};

Why do this happens?

Upvotes: 0

Views: 198

Answers (4)

user2249683
user2249683

Reputation:

Base class and class members are initialized in order of declaration (virtual base classes are different):

  • Base classes (first) in order of declaration (Eg. class X : A, B, C }
  • Members in order of declaration (Eg. int a; int b; int c;)

The order at initialization in a constructor does not change it.

In your case Foo is uninitialized, hence Bar and it's members - undefined behaviour (s has some rubbish data while assigning to it).

Upvotes: 0

AnT stands with Russia
AnT stands with Russia

Reputation: 320371

"Runtime error"? There's no "runtime error" when assigning to an uninitialized member. In C++ the state of "being uninitialized" is not detectable at run-time, which is why it cannot possibly be handled in any deterministic manner (like with "runtime error").

When you do something like that, your code exhibits undefined behavior. The away this undefined behavior will manifest itself is unpredictable. It can easily be sensitive to completely unrelated factors, like declaring another member in the class. That's all there is to it.

Upvotes: 1

deeiip
deeiip

Reputation: 3379

I tried to debug your code. It seems that, when you write:

Bar() : Foo(s = f()) {}

The s object is not properly created yet. Because constructor call of Foo() is not complete yet. Basically it is in a undefined state. So any behaviour will be undefined. But this code behaviour is not undefined:

Bar() : Foo(/*anything*/) {
        s = f();
    } 

Because the constructor call is complete.


Note: I tested in msvc11

Upvotes: 0

Raxvan
Raxvan

Reputation: 6505

When f() executes the class Bar is uninitialized so the member 'a' has no value. It's interesting that this code runs in visual studio 2008 but in any case this is not safe to do.

Razvan.

Upvotes: 0

Related Questions