How to have an instance of subclass in the superclass

How can I declare my subclass and superclass in a way which:
a) my subclass can inherit from superclass
b) superclass have an instance member of subclass

I find this problem inherently confusing since reaching either goal requires a different order of declaration of these classes; and I'm looking for a way to solve this problem complying with good practices.
Last edited on
tricky but possible, you cant create an instance of a type unless it is completely specified, so the compiler knows how much memory it needs. Even a forward declaration wont work for you here.

1
2
3
4
5
6
7
8
9
10
11
class derived;

class base
{
    derived d;
};


class derived : base
{
};

main.cpp:10:13: error: field 'd' has incomplete type 'derived'

but it will if you use a pointer :) because the problem is moved to runtime instead of compile time. At which point all of you rtypes should be complete (or it wouldnt have compiled)


1
2
3
4
5
6
7
8
9
10
11
class derived;

class base
{
    derived* d;
};


class derived : base
{
};


Last edited on
and I'm looking for a way to solve this problem complying with good practices.
You can't because it is always considered a bad design. The super class shall not know anything about the derived class.

What problem are you trying to solve? Most likely there is a better way to do it.
oh yeah, i should have read more carefully!

my example works but Coder777's answer is the correct one :)
CRTP can be very useful when properly applied.
1
2
3
4
5
6
7
8
9
template <typename Derived>
struct B : public Derived 
{
  // B is-a Derived
};

// Later:
struct C : B<C> 
{ /* ... */ };

Obviously each B<Derived> is a different type for every Derived. This doesn't always matter, but one way to avoid this is to inherit from a base class A.
Last edited on

You can't because it is always considered a bad design. The super class shall not know anything about the derived class.

What problem are you trying to solve? Most likely there is a better way to do it.

Thanks you're right, actually I'd mark your answer as the correct one.


CRTP can be very useful when properly applied.
1
2
3
4
5
6
7
8
9
template <typename Derived>
struct B : public Derived 
{
  // B is-a Derived
};

// Later:
struct C : B<C> 
{ /* ... */ };

Obviously each B<Derived> is a different type for every Derived. This doesn't always matter, but one way to avoid this is to inherit from a base class A.

To tell the truth I didn't know what CRTP is when I looked that up I found your answer to be genuinely smart, correct me if I'm wrong if I'm to do that I have to introduce a template argument to my base class and derive my derived class from that in the way you mentioned so instead of using class B which I wanted to have an instance C if I use the C class itself, it will provide me with service I implemented and also has that C instance that I wanted; is that correct?
Last edited on
I made a mistake - that example is wrong. I meant something like this:
1
2
3
4
5
6
7
8
9
template <typename Derived>
struct B /* : public Derived */ 
{
  // B is-a Derived
};

// Later:
struct C : B<C> 
{ /* ... */ };


You work with the C, which is a sub-class of B<C>. Simultaneously, B<C> can borrow functionality from C.

The advantage of this is that you can work with the interface of C, the derived class, from the implementation of B<C>, the base class, as-if B<C> had a C. The base class gains behavior from its derived classes.

For this reason, CRTP is sometimes called "backwards polymorphism".

For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>

template <typename Derived>
struct person 
{
    void greet() 
    { static_cast<Derived*>(this)->do_greet(); }

    void do_greet() const
    { std::cout << "Hello!\n"; }
};

struct mbozzi : person<mbozzi>
{
    void do_greet() const
    { std::cout << "Hi, I'm mbozzi!\n"; };
};

struct stranger : person<stranger> {};

int main() 
{
    mbozzi me;
    stranger s;
    me.greet();
    s.greet();
}


Just like virtual functions...

See also this example:
http://www.cplusplus.com/forum/general/220967/#msg1015575
Last edited on
Topic archived. No new replies allowed.