2016-03-29 2 views
1

У меня есть шаблонный базовый класс, который имеет несколько дочерних классов и предоставляет абстрактный метод выполнения. Дети реализуют этот метод разными способами и могут делегировать выполнение вызовов объектам в хвостовом векторе базового класса. Чтобы связать объекты с хвостом, базовый класс предоставляет некоторые методы (createChild1, createChild2). Вот код:Циркулярная зависимость в шаблонной иерархии наследования

base.h

#pragma once 

#include <memory> 
#include <vector> 

template<typename T> 
class Child1; 

template<typename T> 
class Child2; 

template<typename T> 
class Base { 
public: 
    std::vector<std::unique_ptr<Base<T>>> tail; 

    virtual void execute(const T &t) = 0; 

    Base<T> &createChild1() { 
     auto child = std::make_unique<Child1<T>>(); 
     tail.push_back(std::move(child)); 
     return *tail.back().get(); 
    } 

    Base<T> &createChild2() { 
     auto child = std::make_unique<Child2<T>>(); 
     tail.push_back(std::move(child)); 
     return *tail.back().get(); 
    } 
}; 

child1.h

#pragma once 

#include "base.h" 

template<typename T> 
class Child1 : public Base<T> { 
public: 
    virtual void execute(const T &t) { 
     // do something with t 
    } 
}; 

child2.h

#pragma once 

#include "base.h" 

template<typename T> 
class Child2 : public Base<T> { 
public: 
    virtual void execute(const T &t) { 
     // do something with t 
     // then delegate to t 
     for (auto &next : tail) { 
      next->execute(t); 
     } 
    } 
}; 

main.cpp

#include <iostream> 

#include "child1.h" 

using namespace std; 

int main(int argc, char **argv) { 
    Child1<int> c; 
    c.createChild2().createChild1(); 
    c.execute(10); 
    return 0; 
} 

Если я попытаюсь скомпилировать, я получаю «неявное создание неопределенного шаблона« Child2 », потому что в Base класс шаблона Child2 объявлен только вперед, и его тело в данный момент неизвестно. Переадресация объявления Base перед Child1 и Child2 и включение определений Child1 и Child2 в Base не решает проблему, потому что тогда Child2 не может получить доступ к хвосту. Как я могу решить эту круговую зависимость? Код в Child1, Child2 и Base может меняться, но я хочу сохранить возможность связывать вызовы create в main (поэтому методы create должны быть объявлены в классе Base).

+0

Вы должны быть в состоянии переместить определение 'Base & createChild1()' и 'Base & createChild2()' в файл с именем base.tpp, а затем сделать что последний файл, который вы включаете в основной файл. Это своего рода хакки, поэтому я просто предлагаю это как комментарий. – NathanOliver

+0

Фактически замена хвоста этим-> хвостом делает работу. В любом случае, спасибо :) – freakout

ответ

0

Решение было префикс доступа к хвосту с этим->. Поэтому просто child2.h должен быть изменен:

#pragma once 

#include "base.h" 

template<typename T> 
class Child2 : public Base<T> { 
public: 
    virtual void execute(const T &t) { 
     // do something with t 
     // then delegate to t 
     for (auto &next : this->tail) { 
      next->execute(t); 
     } 
    } 
}; 
Смежные вопросы