Virtual Functions and Vector Iterator

I am having problems with this particular piece of code: It seems that the virtual functions are not working as I expected.

#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; } 

I expected to see:

 From CRectangle: Rectangle From CTriangle: Triangle 

instead I get:

 From CPolygon: Rectangle From CPolygon: Triangle 

Is this the expected behavior? How can I call the Print () function to get the expected result?

+4
source share
1 answer

Is this the expected behavior? How can I call the Print () function to get the expected result?

Yes, this is the expected behavior.

The problem is that standard containers, including vector , have semantics of values: they store copies of the objects you pass to push_back() . On the other hand, polymorphism is based on referential semantics — links or pointers are required for proper operation.

What happens in your case is that your CPolygon object gets a cut that you don't need. You should store pointers (possibly smart pointers) in your vector, not objects like CPolygon .

This is how you should rewrite your main() function:

 #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; } 

Here is a living example .

+5
source

Source: https://habr.com/ru/post/1483934/


All Articles