简体   繁体   中英

How to use forward declarations for a template class in a shared pointer (in C++)

I have a base class Base defined in Base.h :

class Base
{ /* ... */ };

And a class template Child that derives from Base , defined in Child.h :

#include "Base.h"

template <class T>
class Child : public Base
{ /* ... */ };

Now I want to create some factory methods within the Base class, which should return a std::shared_ptr to the Child class. To avoid circular dependencies I tried to use a forward declaration instead. So Base.h now looks like this:

class Child; // new forward declaration

class Base
{
    /* ... */

    // new factory method
    static std::shared_ptr<Base> CreateChildInt(int i = 0)
    {
        return std::make_shared<Child<int>>(i);
    }
};

However, the definition of CreateChildInt() leads to the following compiler error:

"error C2947: expecting '>' to terminate template-argument-list, found '<'"

So is this even possible what I am trying to achieve?
If not, are there any workarounds / best practices for this approach?

EDIT : The reason for why I want to put the factory method into the Base class instead of Child is the following. When I put the factory into Child I would need to call the factory method like this:

std::shared_ptr<Base> p = Child<int>::CreateChildInt(3);

However, I would like to omit the template type <int> in this call, thus:

std::shared_ptr<Base> p = Base::CreateChildInt(3);

Firstly, you declared a class, but Child that you define is actually a template. The correct way to declare a class template is:

template <class T>
class Child;

However, a correct forward declaration alone won't help you. The implementation of CreateChildInt::CreateChildInt must know the full definition of Child because it creates an instance of it. You can't define Child before Base either, because inheritance also depends on the full definition, so you'd end up with a cicrular dependency.

Solution: Forward declare Child , then define Base but don't define Base::CreateChildInt inline, then define Child and finally define Base::CreateChildInt .


PS. I find it dubious from OOP perspective that the implementation of the base class member function depends on the child class. I recommend that you consider re-designing your approach.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM