2013-06-01 48 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上问一个新问题(不,两个新问题!:))(但是别忘了做一些研究首先,答案可能已经在那里) –