1

我想做的是我有一个清单std::list<Displayable> display_queue

Displayable 定义Displayable.h为:

class Displayable { 

    public:

        int x, y;

        Displayable() : x(0), y(0) {}
        Displayable(int x, int y) : x(x), y(y) {}

};

并且DifferentDisplayable作为:

class DifferentDisplayable : public Displayable { 

    public:

        std::string id;

        DifferentDisplayable() : Displayable(), id("") {}
        DifferentDisplayable(int x, int y) : Displayable(x, y), id("") {}
        DifferentDisplayable(int x, int y, std::string id) : Displayable(x, y), id(id) {} 

};

添加到列表中的项目是:

Displayable disp_one;
DifferentDisplayable disp_two(10, 10, "the id");

display_queue.push_back(disp);
display_queue.push_back(disp_two);

由于DifferentDisplayable派生自Displayable它可以存储在列表中,但我无法弄清楚的是,当迭代列表(display_queue)时,我如何或什至可以访问std::string idDifferentDisplayable如下所示:

for (std::list<Displayable>::iterator i = display_queue.begin(); i != display_queue.end(); i++) {

    // insert code here

}

提前感谢您的任何答案

4

2 回答 2

2
std::list<Displayable> display_queue;

该列表只能Displayable包含对象,但不能包含任何派生的子对象。当您尝试这样做时display_queue.push_back(disp_two);,对象被切片,并且仅基类子对象存储在列表中。

于 2013-09-18T17:26:01.373 回答
1

如果所有派生类都不需要“id”,那么不要尝试直接从循环中访问它,而是添加一个使用它的基类方法。例如:

class Displayable
{
public:
  virtual void Display();
  ...
};

(更好的做法是让'class Displayable'成为一个抽象基类,Display() 作为一个纯虚函数。请参阅下面的链接。)

然后实现可以独立变化:

void Displayable::Display()
{
  // Do something here with 'x' and 'y'
}

void DifferentDisplayable::Display()
{
  // Do something here with 'x', 'y', and 'id'
}

然后在堆上分配你的对象以避免切片问题:

Displayable* disp_one = new Displayable();
DifferentDisplayable* disp_two = new DifferentDisplayable(10, 10, "the id");

display_queue.push_back(disp);
display_queue.push_back(disp_two);

然后你的循环变成:

for (std::list<Displayable>::iterator i = display_queue.begin(); i != display_queue.end(); ++i) {
  (*i)->Display();
}

完成后请记住“删除”指针。

此策略在Scott Meyers 的Effective C++ 3rd Edition中的Open-Closed 原则和第34 条“接口继承与实现继承之间的区别”中进行了讨论。

于 2013-09-18T18:11:05.230 回答