How to create an abstract class array in C ++

I am trying to create a program that takes an order for food and prints it. I have a base class Foodthat has a pure virtual function in it. The Food class has 2 subclasses Pizzaand Dessert. I am trying to create an array Foodin mine main, so when the client orders Pizzaor Dessert, it will be saved in the array Food. But every time I try, I get an error message. How do I put two elements together if I want to use a loop to go through each element ordered by the client? This is my code:

int main()
{
  Dessert d("brownie");
  Pizza p("BBQ delux");
  Food array[2] = {d,p};
}

This is my error message. (NOTE: get_set_price()and print_food()- my pure virtual functions, which are defined in the base class and implemented in two subclasses)

main.cpp:37:14: error: invalid abstract type β€˜Food’ for β€˜array’
  Food array[2] = {d,p};

In file included from main.cpp:4:0:
Food.h:5:7: note:   because the following virtual functions are pure within β€˜Food’:
 class Food
       ^

Food.h:20:15: note:     virtual void Food::get_set_price()
  virtual void get_set_price()=0;
               ^

Food.h:27:15: note:     virtual void Food::print_food()
  virtual void print_food()=0; 
               ^

main.cpp:37:22: error: cannot allocate an object of abstract type β€˜Food’
  Food array[2] = {f,o};
                  ^
+5
source share
3 answers

You cannot instantiate abstract classes, but you can assign specific derived instances to pointers or references of the base class.

int main()
{
  Dessert d("brownie");
  Pizza p("BBQ delux");
  Food* array[2] = {&d,&p};
}

then work with array

array[0]->print_food();
+17
source

To do this, you need reference semantics, because it Food arr[2];tries to initialize the array with default values ​​(which are abstract, and therefore non-constructive).

I think it std::array<std::unique_ptr<Food>, 2> arr;should be the most natural to use in this case.

std::array<std::unique_ptr<Food>> arr = {
    std::make_unique<Dessert>("brownie"),
    std::make_unique<Pizza>("BBQ delux")
};

, , initializer_list .

for (auto f : std::initializer_list<Food*>{&d,&p})
    f->commonMemberFunction();

, {}, , , ,

+10

Starting with C ++ 11, you can also use std::reference_wrapper. This is very similar to @Mykola's answer, but uses the links:

#include <functional>  // for std::reference_wrapper

int main()
{
  Dessert d("brownie");
  Pizza p("BBQ delux");
  std::reference_wrapper<Food> array = {d, p};

  // just to see they're references, they have same memory addresses as
  // the initial variables.
  for (const Food &f : array) {
    std::cout << &f << " ";
  }
  std::cout << "\n" << &d << " " << &p << "\n";
}

Unfortunately, the same limitation applies to this and to the version with pointers. You need to define local variables, you cannot just use anonymous objects here.

This will not work:

  std::reference_wrapper<Food> array = {Dessert("brownie"), Pizza("BBQ delux")};
+2
source

Source: https://habr.com/ru/post/1611583/


All Articles