2013-10-16 62 views
0

我剛在程序中發現了一些非常奇怪的行爲。我有一棵樹,每個節點都是Node的子類。通過遍歷樹遞歸地計算邊界框,直到我到達葉節點處的單元基元(即Cube : Node)。C++中的多態遞歸調用?

遞歸函數getBoundingBox()被聲明爲虛擬並正確遍歷樹。葉節點覆蓋函數並返回一個單位立方體。

但是,當我跟蹤程序時,它看起來覆蓋對遞歸函數getBoundingBox()沒有影響,即使它對getName()等其他函數也適用。

例子:

class Node; 

typedef shared_ptr<Node> node_ptr; 

class Node 
{ 
protected: 
    vector<node_ptr> mChildren; 
public: 
    virtual string getName() { return "Node";} 
    virtual BoundingBox getBoundingBox() 
    { 
    //Merge Bounding Boxes of Children 
    BoundingBox bb = BoundingBox(); 
    //For each child 
    for(vector<node_ptr>::iterator it = mChildren.begin(); it != mChildren.end(); ++it) { 
     string name = (*it)->getName();//Correctly returns Node or Cube depending on type of (*it) 
     bb = BoundingBox::Merge(bb, (*it)->getBoundingBox());//Always calls Node::getBoundingBox(); regardless of type 
    } 
    return bb; 
    } 
}; 

class Cube : public Node 
{ 
public: 
    virtual string getName() { return "Cube";} 
    virtual BoundingBox getBoundingBox() 
    { 
    return BoundingBox::CreateUnitCube(); 
    } 
}; 

是否有某種關於C++遞歸多態性我失蹤的警告嗎?

+0

@Kyle下加入它的代碼示例 – CodeFusionMobile

+0

什麼CreateUnitCube做的?是不是所有的立方體都有完全相同的邊界框(例如,你沒有考慮節點的位置) – benjymous

+1

當你寫一個函數,你希望覆蓋某些東西時,你應該習慣於用覆蓋關鍵字。利用多態性捕獲大量「問題」。 – Kindread

回答

0

Cube不是Node,因爲您沒有使用公共繼承。

我不知道你的實際代碼怎麼連編譯,而是試圖將其改爲:

class Cube : public Node 
+0

技術上,類的默認繼承是私有的,並且在結構上是公共的(結構和類之間的「其他」差異) – Salgar

+0

這是一個錯字,更正了 – CodeFusionMobile

+0

這應該以同樣的方式影響'getName()'。 – Walter

1

我想你的繼承結構插手了。它更有意義,有一個基類Node這可能是抽象的

class BaseNode { 
public: 
    virtual BoundingBox getBoundingBox() const = 0; 
}; 

然後定義不同類型的節點

using node_ptr = std::shared_ptr<BaseNode>; 
class Node : public BaseNode 
{ 
    std::vector<node_ptr> mChildren; 
public: 
    BoundingBox getBoundingBox() const noexcept 
    { 
    BoundingBox bb; 
    for(auto pc:mChildren) 
     bb.merge(pc->getBoundingBox()); 
    return bb; 
    } 
}; 

class Cube : public BaseNode 
{ 
public: 
    BoundingBox getBoundingBox() const noexcept 
    { return BoundingBox::CreateUnitCube(); } 
};