Здравствуйте, Acteon, Вы писали:
A>Подход 6. Потерялось наследование Concreate от Base.
Не потерялось. Base и Concrete — финальные классы.
Если хочется сделать наследование в духе CRTP, то нужно делать так
template<class Final> class BaseT // <class Final> - аналог vfptr у обычного наследования
{
void foo() { static_cast<Final*>(this)->bar("hello"); } // косвенное обращение к самому себе - аналог виртуального вызова
void bar(const char* s) {}
.....
};
class Base : public BaseT<Base> {}; // финальный класс для данного шаблона
template<class Final> class DescendantT : public BaseT<Final>
{
int bar(string s, int n=123) {} // перекрытие, причём в весьма свободной форме
.....
};
class Descendant : public DescendantT<Descendant> {};
template<class Final> class FarDescendantT : public DescendantT<Final>
{
// если перекрытия нет, то заимствуем из базового класса
};
class FarDescendant : public FarDescendantT<FarDescendant> {};
A>А зачем класс Concrete дружит с классом friend class BaseT<Base>; ? И кстати, зачем вообще объявлена дружба с классом, от которого мы наследуемся?
Затем, что перегружаемый член m_thread (к которому обращается базовый класс) засунут в private:
A>Подход 7. В бусте потоки в связке с биндерами очень мощные. Но к сожалению, я вынужден использовать Qt для этих целей. Работаем с тем, что есть, а не с тем чем хочется.
Но хотя бы boost:: / std::tr1:: bind можно использовать?
Всегда же можно сделать санки (thunk) в ООП-стиль.
template<class Fun> struct FunThread
{
Fun m_fun;
explicit FunThread(Fun fun) : m_fun(fun) {}
virtual void run() /*override*/ { m_fun(); }
};
template<class Fun>
shared_ptr<Thread> makeFunThread(Fun fun)
{
return shared_ptr<Thread>(new FunThread<Fun>(fun));
}
И не рожать класс на каждый новый вид потока, а конструировать из шаблона прямо на месте.
A>В общем пока примерял все подходы, родилась еще одна идея. Унаследовать класс Base от класса Thread. Получилось что-то на подобие вот этого здесь Критика приветствуется.
Ну, в принципе, так нередко делают. Когда объект — сам себе представитель потока (или, кстати, представитель окна).
Есть два подхода к архитектуре.
— с иерархией тяжеловесных объектов, реализующих поведение потоков, окон, и т.п.
— с единообразными хэндлами и разнообразными объектами-владельцами, не обязательно связанными в одну иерархию.
Для Qt, как и для многих ООП-фреймворков, характерно первое.
Тут надо смотреть на цену этого склеивания. Потому что потом расклеить объект на поток и всё остальное будет мучительно.
Но если расклеивать не собираешься, то почему бы и нет?