在這裏解開循環繼承的好方法是什麼?在C++中混合使用好奇的循環繼承
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()
返回的類型。如果從 Node
HasImportance
繼承,那麼它認爲neighbors()
回報 Node*
一個列表,而不是TrafficLight*
,因此不 知道,它可以在項目叫receive_importance()
。類似 問題如果HasImportance
根本不繼承。
順便說一句,我想要做的是做一些混合,以幫助很容易定義各種各樣的圖形 和單獨測試每個混合。例如,對於 示例,我應該能夠通過編寫 (如class TrafficLight : public HasImportance, HasState<3>, virtual Node { }
)來定義交通信號燈圖的節點類。
我想出了三種方法來解決這個問題,但都顯得很醜陋。 (1) static_cast<NodeType*>
。 (2)TrafficLight
在其構造函數中將其 this
傳遞給HasImportance
。這樣, HasImportance
根本不需要繼承;它只存儲一個指向(ahem)本身的指針 ,而模板參數提供了指針 的類型。 (3)作出Node
類模板,像這樣:
template<class NodeType>
class Node {
public:
list<NodeType*> neighbors() { /* ... */ }
}
class TrafficLight : public HasImportance<Node<TrafficLight>> { /* ... */ }
,編譯,並沒有引進this
, 無償複製,但它似乎......有點太好奇。
這裏有代碼味道嗎?我應該以完全不同的方式處理這些圖表嗎?
在CRTP中使用'static_cast(this)'是* normal *。 –
kennytm
@KennyTM:我甚至會走得這麼遠,並說這是使用CRTP的關鍵 – PlasmaHH
謝謝。我對使用static_cast感到畏懼,因爲它似乎忽略了一個標誌(一種「味道」),即某種更深層的錯誤。如果在CRTP中是「正常」的話,我想我不會那麼反感。這是我的第一個CRTP。你能告訴? :) –