вперед объявить производный класс из шаблона c ++

У меня возникли проблемы с устранением некоторых изломов в реализации дизайна. Это выглядит примерно так:

У меня есть базовый класс шаблона, у которого есть метод преобразования.

// Foo.h

class Bar;

template<typename T>
class Foo {

    virtual const Bar toBar();

}

Я хочу, чтобы производный класс Bar унаследовал от определенной формы Foo, например:

// Bar.h
class Bar : public Foo<float> {
    // Insert Bar methods here, Etc.
}

Поскольку Foo является шаблоном, реализация должна быть полностью определена в заголовке, это вызывает проблему, заключающуюся в том, что реализация метода toBar () должна будет иметь возможность создавать экземпляр типа Bar. Это говорит о том, что мне нужно включить файл заголовка Bar.h после определения Foo, но до реализации Foo.

Однако в Bar.h класс Bar является производным от Foo, поэтому необходимо предоставить полное определение Foo. Это вызывает проблемы, потому что два файла имеют циклическую зависимость, которая не может быть решена с помощью предварительных объявлений, поскольку прямое объявление является производным классом.

Это становится еще более сложным, если другой класс SomeClass имеет член данных типа Bar, поскольку это необходимо, включая Bar.h, который включает Foo.h, который (поскольку это шаблон) включает Bar.h.

Да, и просто для ясности, все файлы заголовков имеют защиту включения, используя

#ifndef _HEADER_NAME_H_
#define _HEADER_NAME_H_
...
#endif

Как другие люди решали подобные сложные проблемы?

В качестве более конкретного примера скажем, что у меня есть класс Array, у которого есть метод преобразования его в удобочитаемый класс String, такой как toString () ... однако класс String объявлен как существующий как

class String : public Array<char> {...};

Заранее спасибо. Гэри.


person Gary Doublé    schedule 15.09.2011    source источник
comment
Может быть, в качестве возвращаемых значений использовать указатели, а не сами экземпляры?   -  person Griwes    schedule 16.09.2011
comment
В шаблоне есть что-то неприятное в виртуальном. Похоже, что две разные идеи сливаются воедино (полиморфизм против специализации).   -  person Skizz    schedule 16.09.2011
comment
@Skizz Это так, что производные классы имеют возможность расширять и переопределять. Может быть, я мог бы вместо этого использовать sspecialisation и typedef? EG: typedef Array ‹char› Строка; шаблон ‹› class Array ‹Char› {String toSting (); / * Строковые методы специализации (например, обрезка и т. Д. * /}   -  person Gary Doublé    schedule 16.09.2011
comment
@Skizz: Вы когда-нибудь слышали о методах стирания шрифтов, основанных на смешивании шаблонов с виртуальными функциями? Не то чтобы здесь дело с OP.   -  person K-ballo    schedule 16.09.2011
comment
@Gary: Я имею в виду, что виртуальный подразумевает общий базовый класс, шаблоны - это разные классы. Итак, я бы: template<typename T> class Foo : public IBaseClass { } и определил IBaseClass как чистый виртуальный базовый класс.   -  person Skizz    schedule 16.09.2011
comment
@ K-балл: Нет, я не слышал о них ... переходит в Google ...   -  person Skizz    schedule 16.09.2011


Ответы (1)


Чтобы Foo< float > был базовым классом, он должен быть полностью определен точкой определения Bar. Однако Foo не обязательно знать о Bar, если вы можете сделать Bar зависимым именем типа в Foo.

Может быть достаточно прямого объявления Bar перед определением Foo. Если вы разместите / свяжете более конкретный код, я могу дать вам лучший ответ.

Попробуй это:

class Bar;

template< typename T, typename DependantBar = Bar >
class Foo {

    virtual const DependantBar toBar();

}
person K-ballo    schedule 15.09.2011