1

I would like to iterate over different objects that all inhereit from the same superclass. That means I have a superclass like this:

class fruit
{
   public: 
      fruit()
      {
      }
};

And I have subclasses like this, which define the objects that are used in my code:

class apple: public fruit
{
   public: 
      apple()
      {
      }
};

class banana: public fruit
{
   public: 
      banana()
      {
      }
};

Now I want to iterate over all fruits (apples, bananas):

for ( first fuit; last fruit; next fruit )
{
    // do something, no matter if apple or banana
}

But how should I do this since apples and bananas are different class types, but they share the same superclass. This is why I think, that there has to be an elegant way to do it.

Lemonbonbon
  • 686
  • 5
  • 25
  • 1
    related/dupe: http://stackoverflow.com/questions/2080020/what-is-the-real-significanceuse-of-polymorphism – NathanOliver May 02 '17 at 18:02
  • 1
    And what is the container that holds "all fruits"? Because you can't iterate over some nebulous concept like "all fruits", you can iterate over a container however. – StoryTeller - Unslander Monica May 02 '17 at 18:03
  • 1
    To iterate, you need a container. You failed to mention whether this is an array, vector, linked list, etc. – PaulMcKenzie May 02 '17 at 18:04
  • What container are you storing the fruit in/how was it declared? If it's something like `std::vector> fruits;` then why can't you simply do `for (const auto& a_fruit : fruits) ...`? – Jesper Juhl May 02 '17 at 18:06
  • I dont think there is a container in my example. I just create `apples` and `banana`s. I thought I dont need an extra container to sort them in, because they should be recognized as `fruits`, because they inherit from the `fruit`-superclass. – Lemonbonbon May 02 '17 at 18:08
  • 1
    StoryTeller is right, you need a container. You can't just iterate "over all fruits". – HolyBlackCat May 02 '17 at 18:10
  • @Lemonbonbon So you thought they would just magically be stored *somewhere* for you that you could then iterate over? Sorry; C++ doesn't work like that. If you want to access your objects later you need to store them somewhere - *explicitly* - *then* you can iterate the container you stored them in. – Jesper Juhl May 02 '17 at 18:12
  • @Lemonbonbon -- You don't have any apple or banana objects in your code. You defined classes called `fruit`, `apple`, and `banana`, but that's all they are -- classes. The actual fruits have to be **instantiated**, i.e. created. So you would need to create them, but they're just going to be totally independent of each other. You then need to group the ones you're interested in a single container, and work with that container. That's how this thing works. – PaulMcKenzie May 02 '17 at 21:41

1 Answers1

1

C++ doesn't have any kind of built-in object registry where you can get access to every existing object of a particular type. However, C++ has multiple container types that can be used to store multiple objects in a variety of different data structures.

Since the objects you are storing are of different types but with a common base type, you need to use pointers or references to achieve polymorphic behavior and avoid object slicing.

For example, you can use a vector of std::unique_ptr objects.

std::vector<std::unique_ptr<fruit>> fruits;

fruits.emplace_back(new apple);
fruits.emplace_back(new banana);

for (auto &fruit : fruits) {
    // fruit is a reference to the unique_ptr holding the pointer-to-fruit. Use
    // the "indirect access to member" operator -> to access members of the
    // pointed-to object:

    fruit->some_method();
}

The advantage of using this approach (vector of unique_ptr objects) is that your apple and banana objects are automatically destroyed when the vector is. Otherwise, you have to delete them manually, and that is a very error-prone approach.

Community
  • 1
  • 1
cdhowie
  • 158,093
  • 24
  • 286
  • 300