0

So I have the main parent class called item and that class has 2 child classes called book and periodical. The ideas behind what I am trying to do is have a polymorphic array or a polymorphic vector that would be able to do something like this: Now the example is in C# (but I want to do it in C++)

    item [ ] items = new items [100]; 
    items[0] = new book(); 
    items[1] = new periodical();
    for (int i = 0; i < items.size; i++ ) {
            items[i].read();
    }

Like I said, the small example code is in C# but I want to do this in C++ but I am not sure how to go about going it. I wanted to use arrays but I'm my research, I haven't found a clear way of how to accomplish this. I also thought if vectors were possible to use or this but I was not sure about that either.

paolo
  • 2,345
  • 1
  • 3
  • 17
  • 3
    Try with a `std::vector> items` – paolo Jul 12 '22 at 13:42
  • Ok thank you for the help and I have booked marked the page. Is there something similar for using vectors with classes. For example when I want to access the class, how would I go about doing that. `items.push_back(book());` that gives me error `items[0].read();` – Brandon Wright Jul 12 '22 at 14:01
  • 1
    I don't mark as dupe, but probably you fill find everything you need here https://stackoverflow.com/questions/2391679/why-do-we-need-virtual-functions-in-c then just extrapolate the examples to have std::vector of pointers to base class – pptaszni Jul 12 '22 at 14:01
  • thank you i will read it now – Brandon Wright Jul 12 '22 at 14:03
  • Thank you to everyone that helped me! I was able to get it working. – Brandon Wright Jul 12 '22 at 18:39

1 Answers1

2

Here is an example (if you have questions let me know):

#include <iostream>
#include <memory>
#include <vector>

class Item
{
public:
    virtual ~Item() = default; // base classes with virtual methods must have a virtual destructor
    virtual void read() = 0;
};

class Book final :
    public Item
{
public:
    void read() override
    {
        std::cout << "book read\n";
    }
};

class Periodical final :
    public Item
{
public:
    void read() override
    {
        std::cout << "periodical read\n";
    }
};

int main()
{
    std::vector<std::unique_ptr<Item>> items;

    // use emplace_back for temporaries
    items.emplace_back(std::make_unique<Book>());
    items.emplace_back(std::make_unique<Periodical>());

    // range based for loop over unique_pointers in items
    // use const& so item cannot be modified and & to avoid copy of unique_ptr (unique_ptr doesn't have a copy constructor)
    for (const auto& item : items)
    {
        item->read();
    }

    return 0;

}
Pepijn Kramer
  • 9,356
  • 2
  • 8
  • 19
  • 1
    _"to avoid copy of unique_ptr"_ The compiler would prevent you from copying it anyway ;) Also, it's somehow confusing you can call non-`const` member function `read` through a reference to a `const std::unique_ptr` (but that depends on the semantics of `const std::unique_ptr`, which behaves like a `T* const` instead if `T const*`) – paolo Jul 12 '22 at 14:21
  • 1
    @paolo true true :) In this case it is really needed (or code will not compile). And yes it may be confusing it can call non const members (didn't want to go into that detail here yet). Mainly just wanted to show dynamic polymorphism using unique_ptr (i.o raw pointers), and a range based for loop ;) – Pepijn Kramer Jul 12 '22 at 14:23
  • Thank you so much, this is what I was looking for thank you. You came in clutch today for your help. – Brandon Wright Jul 12 '22 at 14:32
  • 1
    Beat me to it. My code had the ability to use `operator<<()` for a little extra fun, but that difference alone isn't worth a separate answer. – sweenish Jul 12 '22 at 15:16
  • 1
    @sweenish Hey there is always room for a bit more fun, I'll let you go first next time :) I see now I also should have written down that Item is an abstract baseclass by design. I Prefer interfaces/abstract bases + aggregation over baseclasses with functionality. (Something todo with unit testability, but that too is fun to be had by the OP later) – Pepijn Kramer Jul 12 '22 at 15:35
  • Thank you to everyone that helped me! I was able to get it working. – Brandon Wright Jul 12 '22 at 18:39