Reputation: 425
I have a Java background and I am trying to understand polymorphism in C++. Specifically, how to iterate over a series of subclasses in a std vector defined by their super class, in order to call a specific method. What I would like to do is have the subclasses override the super class method that will be called. However, I am not sure how to do that in C++.
Here is some code to help with celerity:
class Tile {
public:
virtual void drawTile();
}
void Tile::drawTile() {} // not sure if this is needed?
class Tile_Grass : public Tile {
public:
void drawTile();
}
void Tile_Grass::drawTile() { ... do stuff ... }
What I want to do is:
using namespace std;
for (vector<Tile>::iterator itr = tileVector.begin(); itr != tileVector.end(); ++itr) {
itr->drawTile(); // draws Tile_Grass, or any other sub class of Tile, but NOT Tile
}
Right now the for loop only calls "Tile::drawTile()", but I would like to have it call "Tile_Grass::drawTile()", or another subclass of Tile that is in the "tileVector" vector. What am I doing wrong or missing? Thanks in advance!
Upvotes: 2
Views: 1733
Reputation: 1626
You should declare and populate your tileVector with pointers to Tile, not the copy of a Tile object.
Here is a complete Visual Studio 2012 sample project:
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <memory>
class Tile {
public:
virtual void drawTile();
};
void Tile::drawTile() {}
class Tile_Grass : public Tile {
public:
void drawTile();
};
void Tile_Grass::drawTile() { std::cout << "Drawing Tile Grass" << std::endl; }
int _tmain(int argc, _TCHAR* argv[])
{
typedef std::vector<std::unique_ptr<Tile>> TileVector;
TileVector vec;
// add a few Tile_Grass objects
vec.push_back(std::unique_ptr<Tile>(new Tile_Grass()));
vec.push_back(std::unique_ptr<Tile>(new Tile_Grass()));
vec.push_back(std::unique_ptr<Tile>(new Tile_Grass()));
for (auto itr = vec.begin(); itr != vec.end(); ++itr) {
(*itr)->drawTile(); // draws Tile_Grass, or any other sub class of Tile, but NOT Tile
}
return 0;
}
This will output Drawing Tile Grass 3 times.
If, instead, you define your vector to contain an instance of the base class Tile, the objects stored in the vector will be spliced, even if they are originally created as derived Tile_Grass objects:
typedef std::vector<Tile> TileValueVector;
TileValueVector vecv;
// add a few Tile_Grass objects
vecv.push_back(Tile_Grass());
vecv.push_back(Tile_Grass());
vecv.push_back(Tile_Grass());
for (auto itr = vecv.begin(); itr != vecv.end(); ++itr)
itr->drawTile(); // draws Tile
This will print Drawing Tile 3 times, assuming:
void Tile::drawTile() { std::cout << "Drawing Tile" << std::endl; }
What happens in splicing is that only the base object part of the Tile_Grass gets gets copied into vector elements, since you declared that you want the vector containing instances of that base object.
Upvotes: 3
Reputation: 8972
You'll want a vector of Tile*
, or, better yet, std::unique_ptr<Tile>
;
Upvotes: 4