У меня есть два класса, 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.
...
}
Ошибка, естественно, "недопустимое использование неполного типа".
Что вам нужно сделать, так это отделить объявления классов от реализации. Что-то вроде
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>;}
Таким образом, у вас есть полные определения классов, когда определены функции.
Вы должны использовать форвардные объявления шаблонного класса в любом из заголовков.
template <class T>
class X;
- это идеальное форвардное объявление шаблонного класса.
(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