Каков хороший способ расшифровать циклическое наследование здесь?
class Node {
//...
public:
list<Node*> neighbors() { /*... */ }
void update() { }
}
template<class NodeType>
class HasImportance : public virtual NodeType {
double m_importance = 0.0;
public:
void receive_importance(double imp) { /*... */ }
void give_importance() {
for (auto neighbor : this->neighbors())
neighbor->receive_importance(m_importance /*... */);
}
};
class TrafficLight : public HasImportance<TrafficLight>, virtual Node {
public:
list<TrafficLight*> neighbors() {... }
void update() { give_importance(); /*... */ }
};
Он не работает (gcc 4.7.0 ), потому что TrafficLight
является неполным типом когда HasImportance
пытается наследовать от него.
Настоящая проблема заключается в том, что HasImportance необходимо знать тип, возвращаемый neighbors()
. Если HasImportance
наследуется от Node
, то думает, что neighbors()
возвращает список Node*
, а не TrafficLight*
, и, следовательно, не знайте, что он может вызывать receive_importance()
для элементов. Похожий проблема, если HasImportance
вообще не наследуется.
Кстати, я пытаюсь сделать несколько смешанных -входов, чтобы помочь определить различные различные виды графиков легко и для модульного -тестирования каждого микса -в отдельности. За например, я должен иметь возможность определить класс узла для графа светофоров, просто написав что-то вроде class TrafficLight : public HasImportance, HasState<3>,
virtual Node { }
.
Я придумал три способа решить эту проблему, но все они кажутся уродливыми. (1)
static_cast<NodeType*>
. (2)TrafficLight
проходит свой с this
по HasImportance
в его конструкторе. Сюда, HasImportance
вообще не нужно наследовать; он просто хранит указатель на сам (кхм ), а параметр шаблона обеспечивает тип указатель. (3 )Создайте Node
шаблон класса, подобный этому:
template<class NodeType>
class Node {
public:
list<NodeType*> neighbors() { /*... */ }
}
class TrafficLight : public HasImportance<Node<TrafficLight>> { /*... */ }
Это компилируется и не создает бесплатную копию this
, но это кажется… слишком любопытным.
Есть ли здесь запах кода? Должен ли я подходить к этим графикам полностью по-другому?