9

I am trying to create a program that takes food order and prints it out. I have my base class Food which has a pure virtual function in it. Class Food has 2 subclass Pizza and Dessert. I am trying to make an array of Food in my main so when a customer orders Pizza or Dessert, it will be stored in the array of Food. But every time I try, I get an error. How should I put the two items together then if I want to use a loop to go over each item the customer ordered? 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() are my pure virtual functions which is defined in base class and implemented in the 2 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};
                  ^
3
  • 4
    Use pointers or references. Commented Oct 14, 2015 at 10:53
  • @Someprogrammerdude "C++ Standard §8.3.2/4: There shall be no references to references, no arrays of references, and no pointers to references." -> So no, references is not an option! Commented Nov 4, 2023 at 18:15
  • @GURKE While my comment were intended to be more generic, there's still std::reference_wrapper to solve that problem. :) Commented Nov 4, 2023 at 21:31

3 Answers 3

27

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

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

then work with array

array[0]->print_food();
Sign up to request clarification or add additional context in comments.

Comments

12

You need reference semantics for that, because Food arr[2]; tries to initialize the array with default values (which are abstract, thus not constructible).

I think 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")
};

If you just want to loop over those two values, though, using initializer_list would be easiest, I suppose.

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

Unfortunately it won't deduce the correct type from just {}, but a helper could be created, I suppose,

6 Comments

@TartanLlama Doesn't seem to.
Thank you for your reply @Bartek. Could you please tell me what unique_ptr is? Is it a regular pointer or does it have some other attributes.
@SafwanUllKarim it's a pointer that guarantees sole, unique ownership of the value. See the reference for details.
the only issue with this is you have to make sure you deallocate the memory at the end for all those news you did.
@AndreiPetre that's not a problem, since they are all stored in the smart pointers.
|
3

Starting with C++11, you can use std::reference_wrapper too. It's very similar to @Mykola's answer, but uses references:

#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 restriction applies to this and to the version with pointers. You need to have local variables defined, you can't just use anonymous objects here.

This won't work:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.