Разрешение круговой зависимости между шаблонными классами

У меня есть два класса, Foo<T> и Bar<T>, полученный из Base. Каждый переопределяет метод virtual Base* convert(ID) const, где ID экземпляр типа, который однозначно определяет конкретное инстанцирование Foo или Bar (притворитесь, что это enum). Проблема - это Foo::convert() потребности смочь возвратить a Bar экземпляр, и аналогично Bar::convert() потребности смочь инстанцировать Foo. Так как они - оба шаблоны, это приводит к круговой зависимости между Foo.h и Bar.h. Как я разрешаю это?

Править: Предописание не работает, потому что для реализации каждого метода нужен конструктор другого класса:

Foo.h:

#include <Base.h>

template<class T> class Bar;

template<class T>
class Foo : public Base { ... };

template<class T>
Base* Foo<T>::convert(ID id) const {

    if (id == BAR_INT)
        return new Bar<int>(value); // Error.

    ...

}

Bar.h:

#include <Base.h>

template<class T> class Foo;

template<class T>
class Bar : public Base { ... };

template<class T>
Base* Bar<T>::convert(ID id) const {

    if (id == FOO_FLOAT)
        return new Foo<float>(value); // Error.

    ...

}

Ошибка, естественно, "недопустимое использование неполного типа".

21
задан Jon Purdy 28 July 2010 в 14:39
поделиться

3 ответа

Что вам нужно сделать, так это отделить объявления классов от реализации. Что-то вроде

template <class T> class Foo : public Base
{
    public:
    Base* convert(ID) const;
}

template <class T> class Bar : public Base
{
    public:
    Base* convert(ID) const;
}

template <class T> Base* Foo<T>::convert(ID) const {return new Bar<T>;}
template <class T> Base* Bar<T>::convert(ID) const {return new Foo<T>;}

Таким образом, у вас есть полные определения классов, когда определены функции.

21
ответ дан 29 November 2019 в 06:44
поделиться

Вы должны использовать форвардные объявления шаблонного класса в любом из заголовков.

template <class T>
class X;

- это идеальное форвардное объявление шаблонного класса.

13
ответ дан 29 November 2019 в 06:44
поделиться

(Updated) Вы должны быть в состоянии справиться с этим так же, как и с нешаблонными классами. Напишите ваш Bar.h следующим образом. (И аналогично для Foo.h)

#if !defined(BAR_H_INCLUDED)
#define BAR_H_INCLUDED

template <class T>
class Foo;

template <class T>
class Bar
{
    /// Declarations, no implementations.
}    

#include "Foo.h"

template <class T>
Base* Bar<T>::Convert() {  /* implementation here... */ }
#endif
14
ответ дан 29 November 2019 в 06:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: