0

Here is a minimal example. I have a Base class that needs to know the Deriving class. In turn the Deriving class needs to know the Base class. So how can I define them, so that they know of each other's existence?

class Base {
  Deriving* d;
public:
  Base(Deriving* deriving) {
    d = deriving;
  }
  void f() {
    d->g();
  }
};

class Deriving : public Base {
public:
  Deriving() : Base(this) {}
  g();
};

Here is what I tried and what the compiler said: Defining Base first leads to error: 'Deriving' does not name a type. Defining Deriving first leads to error: expected class-name before '{' token. Declaring an incomplete type of Base or Deriving leads to error: invalid use of incomplete type 'class X'. I do not know what else to try.

Any help is greatly appreciated.

mskr
  • 375
  • 5
  • 14
  • Why does it need to know "Deriving", why not just take a pointer to "Base*"? – kfsone Apr 27 '16 at 20:49
  • Because in my program there can be many Base objects pointing to the same Deriving object because of certain reasons. – mskr Apr 27 '16 at 20:55
  • By *object* do you mean instance or class definition? – kfsone Apr 27 '16 at 20:56
  • Can you show how you intend to construct Deriving and Base, please? – kfsone Apr 27 '16 at 21:01
  • In my case Base objects can actually only be constructed by a Deriving object. The Deriving object can be constructed from outside. The Deriving object has a method which constructs a Base object and returns a pointer to it. Why does it matter? – mskr Apr 27 '16 at 21:05
  • Trying to eliminate misunderstanding/miscommunication about polymorphism as the issue. So far as I know, what you're trying to do is impossible because you can't pre-declare a descendant before it's ancestor. Someone else may have a clever multiple-inheritance workaround though, but only if they know you're not just thinking you are responsible for creating an instance of your Base class when you instantiate your Derived. – kfsone Apr 27 '16 at 21:11
  • You have to separate the declaration and definition to solve your problem. Add a class forward `class Derived;` before `Base` so the compiler knows `Derived` and change your functions, ctors, etc. to declarations e.g. `void f();` and add the definitions afterwards e.g. `void Base::f() { d->g(); }`. – tomse Apr 27 '16 at 21:13
  • Maybe [CRTP](http://stackoverflow.com/questions/4173254/what-is-the-curiously-recurring-template-pattern-crtp) woul solve your problem – M.M Apr 28 '16 at 00:32

2 Answers2

2

In Base, only function f needs to know definition of class Deriving, so define it after Deriving is defined .

class Deriving;

class Base {
      Deriving* d;
    public:
      Base(Deriving* deriving) {
        d = deriving;
      }
      void f();
};

class Deriving : public Base {
    public:
      Deriving() : Base(this) {}
      void g();
};

void Base::f()
{
    d->g();
}
PcAF
  • 1,975
  • 12
  • 20
0

This kind of arrangement is normally a logic error. The base class should never need to know anything about the derived class. If a method in the base class needs to use assets that happen to be stored in the derived class, then references to those assets can be passed into the function f().

In the example above, the desired behaviour can be achieved with inheritance:

Something like this:

class Base
{
public:
  void f() {
    impl_f();
  }
private:
  virtual void impl_f() = 0;
};

class Derived : public Base
{
private:
  void impl_f() override
  {
    // whatever g() was going to do...
  }
};
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142