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.
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
{
};
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.
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?
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".