1

What I want to do is that I have a list std::list<Displayable> display_queue

Displayable being defined in Displayable.h as:

class Displayable { 

    public:

        int x, y;

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

};

and DifferentDisplayable as:

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) {} 

};

The items added to the list is:

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

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

Since DifferentDisplayable is derived from Displayable it is able to be stored in the list but what I can't figure out is how can I or can I even access std::string id in DifferentDisplayable when iterating through the list (display_queue) like so:

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

    // insert code here

}

Thanks in advance for any answers

PurityLake
  • 1,110
  • 10
  • 18
  • 2
    [You better read this](http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c). You're about to embark upon an object-slicing problem. – WhozCraig Sep 18 '13 at 17:24
  • 1
    possible duplicate of [push\_back with derived class](http://stackoverflow.com/questions/11540998/push-back-with-derived-class) – n. m. could be an AI Sep 18 '13 at 17:25
  • 1
    duplicate ? http://stackoverflow.com/questions/9241680/list-of-polymorphic-objects – willll Sep 18 '13 at 17:25
  • @WhozCraig By the time I see the issue and post the answer, you already made the comment which I didn't see. Why not post it as an answer when it is the answer ? – Mahesh Sep 18 '13 at 17:28
  • 1
    @Mahesh It falls somewhat into a grey area, and I understand that. The "problem" the OP is *going* to have is the same one addressed in the linked q&a. But the *question* is actually different (but obviously soon-to-be-related). The OP didn't ask "Why does this not work" because they didn't get that far yet. The question essentially was "How do I do this?" and the answer is "Not like *that*." (and +1 on your answer). – WhozCraig Sep 18 '13 at 17:44

2 Answers2

2
std::list<Displayable> display_queue;

The list is capable of holding only Displayable objects but not it's any derived sub-objects. When you try to do display_queue.push_back(disp_two);, object is sliced and only base class sub-object is stored in the list.

Mahesh
  • 34,573
  • 20
  • 89
  • 115
1

If 'id' isn't needed for all derived classes, then instead of trying to access it directly from your loop, add a base class method that uses it. For example:

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

(Even better would be to make 'class Displayable' an abstract base class, with Display() as a pure virtual function. See the links below.)

Then the implementations can vary independently:

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

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

Then allocate your objects on the heap to avoid the slicing problem:

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);

Then your loop becomes:

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

Remember to 'delete' the pointers when you're done with them.

This strategy is discussed in the Open-Closed Principle and in Item 34 "Differentiate between inheritance of interface and inheritance of implementation" in Effective C++ 3rd Edition by Scott Meyers.

snips-n-snails
  • 637
  • 5
  • 22