Caduchon
Caduchon

Reputation: 5201

Classes hierarchy having pointer to themself

I have a class A, needing a pointer to AA to work, required by the constructor. I have a class B inherited from A, providing to A a class BB inherited from AA. Example :

class A
{
  public:
    class AA
    {
      virtual void do_something() const;
    };
  protected:
    const AA* aa;
  public:
    A(const A::AA* aa_) : aa(aa_) {}
    void use() const { this->aa->do_something(); }
};

class B : public A
{
  public:
    class BB : public A::AA
    {
      virtual void do_something() const;
    };
  public:
    B() : A(new BB()) {}
};

Now, I would like to give the address of the B instance to the BB instance. Somthing like that :

class B : public A
{
  public:
    class BB : public A::AA
    {
      BB(B* b);
      virtual void do_something() const;
    };
  public:
    B() : A(new BB(this)) {}
    // It doesn't work beacause the instance is not yet created
};

Or something like that :

class B : public A
{
  public:
    class BB : public A::AA
    {
      virtual void do_something() const;
      void setPointer(B* b);
    };
  public:
    B() : A(new BB()) { static_cast<BB*>(this->aa)->setPointer(this); }
    // It doesn't work because this->aa is const
};

How can I do that ? Is there a design pattern solving this kind of problem ?

Upvotes: 0

Views: 67

Answers (2)

Shoe
Shoe

Reputation: 76240

Making AA::do_something public or protected and BB's constructor public, makes your code compilable.

Refactoring a little you can get a nice version as well:

class A {
public:
    struct AA {
        virtual void do_something() const;
    };

    A(A::AA const* aa_) : aa(aa_) {}
    void use() const { this->aa->do_something(); }
protected:
    AA const* aa;
};

struct B : public A {
    struct BB : public A::AA {
        BB(B* b) {}
        virtual void do_something() const override;
    };
    B() : A(new BB(this)) {}
};

Live demo

Upvotes: 1

If you only want BB:BB to store the pointer, then

    B() : A(new BB(this)) {}

should work just fine.

If you want it to use the pointer, then your best bet is to store the pointer in the constructor, and use it in a second function like this:

   B() : A(new BB(this)) { static_cast<const BB*>(this->aa)->UseStoredThis();

That assumes you can mark UseStoredThis as const. If not, then you will need:

   B() : A(new BB(this)) 
   { 
       const auto pcBB = static_cast<const BB*>(this->aa);
       const auto pBB = const_cast<BB*>(pcBB);
       pBB->UseStoredThis();
   }

Upvotes: 1

Related Questions