0
#include <iostream>
class BarParent
{
    public:
        int x;
        virtual void fuz() = 0;
};

class BarChild : public BarParent
{
    public: 
        BarChild(int new_x){x = new_x;}
        virtual void fuz(){}
};

class FooParent
{
    public:
        BarParent* p_barPar;
        FooParent (BarChild* new_p_bar)
        {
            p_barPar = new_p_bar;
            std::cout << p_barPar->x << std::endl;
        }
};

class FooChild: public FooParent
{
    public:
        BarChild barChild;
        FooChild(int new_x):FooParent(&barChild), barChild(new_x){}
};
int main()
{   
    FooChild foo(60);

    BarChild bar(99);
    FooParent fooP(&bar);
}

Output:

-548726160 
99

I understand why I am getting this result(undefined behavior), barChild is used before it is initiailized. My question is what is the 'right' to do handle this.

aiao
  • 4,621
  • 3
  • 25
  • 47
  • @zneak A simpler MWE would make users suggest to just "reorder the members." – aiao Mar 31 '13 at 20:29
  • as far as I can tell, you only needed a base class that needs to be initialized with a member field. – zneak Mar 31 '13 at 20:55

4 Answers4

2

This is a case where design, not code needs to be fixed.

By your own design:

  • A BarChild must be constructed before FooParent.
  • A FooParent must be constructed before a FooChild.
  • A FooChild must be constructed before a BarChild.

When you want both FooParent and FooChild to refer to this same Bar object - as you're attempting in your code - design the parent class to manage it.

One example solution:

    FooParent (BarChild* new_p_bar)
    {
        if ( new_p_bar == NULL )
           new_p_bar = new BarChild;

        p_barPar = new_p_bar;
        std::cout << p_barPar->x << std::endl;
    }

Here, FooChild doesn't need its own instance of this object.

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
  • > By your own design: > > A BarChild must be constructed before FooParent. A FooParent must be > constructed before a FooChild. A FooChild must be constructed before a > BarChild. I have editted the question to reflect my intentions. I prefer not to use the heap if possible. Please advise. – aiao Apr 01 '13 at 01:17
  • @aiao You should post a new question if you have a new question. This isn't an effective forum for back-and-forth discussions. Good luck! – Drew Dormann Apr 01 '13 at 01:22
0

Respect the order of initialization.

You can create a function inside BarParent to set the pointer p_barPar. Call the function in the constructor of FooChild.

Is there any reason you can't make barChild (in FooChild) a pointer as well?

maditya
  • 8,626
  • 2
  • 28
  • 28
  • yes I need `BarChild` to reside inside `FooChild`. Otherwise I would have a dirty architecture – aiao Mar 31 '13 at 20:34
  • What do you mean by a "dirty" architecture? – maditya Mar 31 '13 at 21:18
  • Your current implementation is not clean either. You have a pointer in your base class that is pointing to a member in the derived class, which is very strange. – maditya Mar 31 '13 at 21:20
0

I think you will have to find another example: this one is wrong because of the RAIII principle which is not enforced: FooParent holds a pointer on a value which it doesn't control. An interesting example of where this setup would fail is the slicing problem.

Community
  • 1
  • 1
didierc
  • 14,572
  • 3
  • 32
  • 52
0

quick and dirty solution:

class FooChild: private BarChild, public FooParent
{
public:
        FooChild(int new_x): BarChild(new_x), FooParent(this) {}
};
green lantern
  • 1,086
  • 7
  • 10