Search code examples
c++inheritancemember-variables

Inherited class initializing a custom made class using non-default constructor


So I have searched all over the place and I can not seem to find the answer to this specific question. I am using a winXP with cygwin and gcc 3.4.4 cygming special.

Problem: I have a class that works as an interface with some abstract methods and protected variables that should be in every class that inherits from this class. Now I also have another class that is a member variable of this interface.

class Bar {
private:
    int y;
public:
    Bar(int why);
};

Bar::Bar(int why) : y(why) {}

class Foo {
protected:
    Bar b;
public:
    Foo(int x);
    virtual void print_base();
};

Foo::Foo(int x) : b(x+3)  // Have to use initializer list here.
{
    //this->b(x+3); // doesn't work
}

class DerFoo : public Foo {
protected:
    Bar db;
public:
    DerFoo(int x);
};

DerFoo::DerFoo(int x) : Foo(x), 
    db(x+3) // (Bar)(int) being called, works fine
    // db(4.0, 30) // no matching function for call to Bar::Bar(double, int)
    // note: candidates are Bar::Bar(const Bar&), Bar::Bar(int)
    // b(x-3) // doesn't work class DerFoo does not have any field named 'b'
{
    //this->b(x - 3); //  Doesn't work, error no match for call to (Bar)(int)
    //this->db(x + 3); // Doesn't work, error no match for call to (Bar)(int)
}

So the problem as you can see is inside the derived foo class, DerFoo how to initialize b. I have tried member initialization method, but then the compiler doesn't realize about protected variables. So then for some bizarre reason unbeknownst to me, it can not find the constructor in this class. Even though if were to include a "wrong" call to the constructor of a protected member variable (non inherited) it would suggest the correct version of the constructor.

I have no clue still how to do this. Any help is greatly appreciated.


Solution

  • DerFoo's constructors must not (and cannot) initialize b, that's Foo job. DerFoo's constructors are responsible for initializing only DerFoo's immediate subobjects, namely db and the Foo which is a base class of DerFoo. Foo's constructor, in turn, is responsible for initializing b.

    The sequence of events is like:

    • DerFoo's constructor invokes Foo's constructor
    • Foo's constructor invokes b's constructor
    • Foo's constructor runs its body, leaving the Foo object completely constructed
    • DerFoo's constructor invoke's db's constructor
    • DerFoo's constructor runs its body, leaving the DerFoo object completely constructed.

    If, in the DerFoo constructor, you don't like the value that the Foo constructor left in b, you can assign a new value to b, using any one of these syntaxes:

    b = Bar(47);
    this->b = Bar(47);
    this->Foo::b = Bar(47);
    Foo::b = Bar(47);