jeudi 25 octobre 2018

C++11 object fields initialization in derived classes [duplicate]

This question already has an answer here:

There is a complex situation with fields initialization. Simplified code snippet follows (compiled with gcc, C++11 enabled):

class One
{   public:
        One()
            { Log("One::One(): GetVal() returns %d",getVal()); };
        virtual int getVal() { return 0; };
};
class Two : public One
{   public:
        Two()
            { Log("Two::Two(): GetVal() returns %d",getVal()); };
        Two(int x) : val(x), One()
            { Log("Two::Two(%d): GetVal() returns %d",x,getVal()); };
        virtual int getVal() { return val; };
        int val = 1;
};

Two* two = new Two(2);
Log("final val = %d",two->getVal());

Expected output:

One::One(): GetVal() returns 2
Two::Two(2): GetVal() returns 2
final val = 2

Real output:

One::One(): GetVal() returns 0
Two::Two(2): GetVal() returns 2
final val = 2

The questions are:

  1. why val field is not initialized in line Two(int x) : val(x), One() {...} before calling parent constructor One()?

  2. why initialization within declaration line int val = 1; does not works too?

  3. How can I init some field before calling parent constructor? Or at least make const initializers (in field declarations) to work?

I guess someone will say such a structure is a bad idea, but I really need it this way - actually, it contains some important data, and for "upper" parent classes in it calculated some way, but for one of derived classes it must be set in constructor, before executing parent constructors (they use this value through getVal()). If it's not possible, I need at least default const initializers to work so I can make some workaround instead of crashing because of garbage in field value.

I had also tried checking dynamic_cast<Two*>(this) in One::One(), but it always returns NULL so I can't make a workaround based on actual object type.

Aucun commentaire:

Enregistrer un commentaire