C ++如何迭代定义为超类的向量,但调用子类方法?

时间:2013-06-19 00:57:10

标签: c++ inheritance polymorphism override stdvector

我有Java背景,我正在尝试理解C ++中的多态性。具体来说,如何迭代由超类定义的std向量中的一系列子类,以便调用特定方法。我想要做的是让子类覆盖将被调用的超类方法。但是,我不知道如何在C ++中这样做。

以下是一些有助于快速的代码:

    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  ... }

我想做的是:

    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
    }

现在for循环只调用“Tile :: drawTile()”,但我想让它调用“Tile_Grass :: drawTile()”,或者是“tileVector”向量中的Tile的另一个子类。我做错了什么或错过了什么?提前谢谢!

2 个答案:

答案 0 :(得分:4)

你需要一个Tile*的矢量,或者更好的是,std::unique_ptr<Tile>;

答案 1 :(得分:3)

您应该使用指向Tile的指针声明并填充您的tileVector,而不是Tile对象的副本。

这是一个完整的Visual Studio 2012示例项目:

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

这将输出 Drawing Tile Grass 3次。

相反,如果您将矢量定义为包含基类Tile的实例,则存储在矢量中的对象将拼接,即使它们最初是作为派生的Tile_Grass对象创建的:< / p>

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

这将打印绘图平铺 3次,假设:

void Tile::drawTile() { std::cout << "Drawing Tile" << std::endl; } 

拼接中发生的事情是,只有Tile_Grass的基础对象部分被复制到向量元素中,因为您声明要包含该基础对象实例的向量。