2013-06-01 50 views
4

我在使用這段特定的代碼時遇到了問題: 虛擬函數似乎不像我期望的那樣工作。虛擬函數和向量迭代器

#include <cstdio> 
#include <string> 
#include <vector> 

class CPolygon 
{ 
protected: 
    std::string name; 
public: 
    CPolygon() 
    { 
     this->name = "Polygon"; 
    } 
    virtual void Print() 
    { 
     printf("From CPolygon: %s\n", this->name.c_str()); 
    } 
}; 

class CRectangle: public CPolygon 
{ 
public: 
    CRectangle() 
    { 
     this->name = "Rectangle"; 
    } 
    virtual void Print() 
    { 
     printf("From CRectangle: %s\n", this->name.c_str()); 
    } 
}; 

class CTriangle: public CPolygon 
{ 
public: 
    CTriangle() 
    { 
     this->name = "Triangle"; 
    } 
    virtual void Print() 
    { 
     printf("From CTriangle: %s\n", this->name.c_str()); 
    } 
}; 

int main() 
{ 
    CRectangle rect; 
    CTriangle trgl; 
    std::vector<CPolygon> polygons; 
    polygons.push_back(rect); 
    polygons.push_back(trgl); 

    for (std::vector<CPolygon>::iterator it = polygons.begin() ; it != polygons.end(); ++it) 
    { 
     it->Print(); 
    } 

    return 0; 
} 

我期望看到:

From CRectangle: Rectangle 
From CTriangle: Triangle 

,而不是我得到:

From CPolygon: Rectangle 
From CPolygon: Triangle 

這是預期的行爲?我應該如何調用Print()函數來獲得我期望的輸出結果?

回答

5

這是預期的行爲?我應該如何調用Print()函數來獲得我期望的輸出結果?

是的,它是預期的行爲。

的問題是,標準容器,包括vector,有值語義:它們存儲副本傳遞給push_back()對象。另一方面,多態性基於參考語義 - 它需要引用或指針才能正常工作。

你的情況發生了什麼是你的CPolygon對象得到sliced,這不是你想要的。您應該在向量中存儲指針(可能是智能指針),而不是CPolygon類型的對象。

這是你應該如何重寫你main()功能:

#include <memory> // For std::shared_ptr 

int main() 
{ 
    std::vector< std::shared_ptr<CPolygon> > polygons; 
    polygons.push_back(std::make_shared<CRectangle>()); 
    polygons.push_back(std::make_shared<CTriangle>()); 

    for (auto it = polygons.begin() ; it != polygons.end(); ++it) 
    { 
     (*it)->Print(); 
    } 

    return 0; 
} 

這裏是一個live example

+0

謝謝!它的工作,我也嘗試過與標準指針的例子,工作得很好。 – mpestkow

+0

什麼是shared_ptr <>和auto?[初學] – Dineshkumar

+0

@Dineshkumar:這是一個廣泛的話題,我建議你在StackOverflow上問一個新問題(不,兩個新問題!:))(但是別忘了做一些研究首先,答案可能已經在那裏) –