【问题标题】:Accessing attributes of a derived class in a std::list访问 std::list 中派生类的属性
【发布时间】:2013-09-18 17:22:28
【问题描述】:

我想做的是我有一个列表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 派生的,它可以存储在列表中,但我不知道我如何或什至可以在迭代时访问DifferentDisplayable 中的std::string id像这样列出(display_queue):

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

    // insert code here

}

提前感谢您的任何回答

【问题讨论】:

  • You better read this。您即将着手解决对象切片问题。
  • @WhozCraig 当我看到问题并发布答案时,您已经发表了我没有看到的评论。既然是答案,为什么不把它作为答案发布呢?
  • @Mahesh 它有点落入灰色地带,我明白这一点。 OP 遇到的“问题”与链接的问答中解决的问题相同。但是 question 实际上是不同的(但显然很快就会相关)。 OP 没有问“为什么这不起作用”,因为他们还没有走到那一步。问题本质上是“我该怎么做?”答案是“不像那个。” (并对您的回答 +1)。

标签: c++ list iterator


【解决方案1】:
std::list<Displayable> display_queue;

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

【讨论】:

    【解决方案2】:

    如果所有派生类都不需要“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();
    }
    

    请记住在使用完指针后“删除”它们。

    Open-Closed PrincipleEffective C++ 3rd Edition by Scott Meyers 的第 34 条“接口继承与实现继承之间的区别”中讨论了此策略。

    【讨论】:

      猜你喜欢
      • 2012-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-28
      • 1970-01-01
      相关资源
      最近更新 更多