I want to make an abstract class, A that will be subclassed by Class B and Class C such that they will all use the same methods in the defined abstract class (B and C are A-able classes).
I have another class, Z, that will contain an array of A-able classes. I would like for it to have a function that allows it to swap between B and C in that array (ie. calling initializer/member function with an argument).
The below example, while not being exactly like what I'm describing above (not using abstract classes), showcases the same issue I'm running into: I'm unable to set the array to the correct subclass, since it's complaining that it was initialized as the parent class.
However, this should be possible to do right? What am I missing here?
#include <iostream>
#include <array>
class BaseItem {
protected:
std::string name;
BaseItem(const std::string & name) : name(name) {};
virtual void printName();
virtual ~BaseItem() = default;
};
class Item1: public BaseItem {
public:
using BaseItem::name;
Item1() : BaseItem("Book1") {}
void printName() {
std::cout << "1" << name;
}
};
class Item2: public BaseItem {
public:
using BaseItem::name;
Item2() : BaseItem("Book2") {}
void printName() {
std::cout << "2" << name;
}
};
class Library {
public:
std::array<BaseItem, 2> books;
void setToItem2() {
for (size_t i = 0; i < books.size(); i++) {
books[i] = new Item2();
}
}
void setToItem1() {
for (size_t i = 0; i < books.size(); i++) {
books[i] = new Item1();
}
}
void printBooks() {
for (auto& entry: books) {
entry->printName();
}
}
};
int main() {
Library a;
a.setToItem1();
a.printBooks();
a.setToItem2();
a.printBooks();
return 0;
}
Edit: Cleaned up a bit, also adding error message below:
prog.cpp: In member function ‘void Library::setToItem2()’:
prog.cpp:36:31: error: no match for ‘operator=’ (operand types are ‘std::array<BaseItem, 2>::value_type’ {aka ‘BaseItem’} and ‘Item2*’)
Edit2: Made the example code more representative of what I want to implement, utilizing code help from some of the existing answers.
Current potential solutions:
- Evict books and pass in the correct subclass. This is currently what I'm going with. Just don't know if there is anything that can make this look cleaner (ie. all the casting looks a bit messy).
- Make books a variant. The code looks cleaner here, but if I'm to extend to Item3, Item4, etc. I'll have to increase the variant to include all those subtypes, which IMHO defeats part of the purpose of making this "interface" (of course, we still get to inherit some shared things, but I'd like to not have to keep adding new classes into variant).
For now, I'm going to just do 1. But please let me know if there is something better.