2

我有 Java 背景,我正在尝试理解 C++ 中的多态性。具体来说,如何迭代其超类定义的标准向量中的一系列子类,以便调用特定方法。我想做的是让子类覆盖将被调用的超类方法。但是,我不确定如何在 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 子类。我做错了什么或错过了什么?提前致谢!

4

2 回答 2

4

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

于 2013-06-19T01:04:56.360 回答
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;
}

这将输出绘制瓷砖草3 次。

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

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 的基础对象部分被复制到向量元素中,因为您声明您想要包含该基础对象实例的向量。

于 2013-06-19T01:10:35.253 回答