简体   繁体   中英

Dereferencing a class pointer function in iterator

I have created a Vector of pointers to a class called Food

vector<Food*> items;

The class looks like the following:

 class Food
 {
   private:
    string name;
    int month;
    int year;

   public:
    void display()
    {
      cout << name << " - " << month << "/" << year << endl;
    }
  }

I then have created a function to prompt these items

void promptInventory(vector<Food*> &items)
{
   string name;
   int month;
   int year;

   do
   {
      cout << "Enter item name: ";
      getline(cin, name);

      if (name != "quit")
      {
         cout << "Enter expiration month: ";
         cin >> month;

         cout << "Enter expiration year: ";
         cin >> year;

         cin.ignore();

         Food * food = new Food;;

         food->setName(name);
         food->setMonth(month);
         food->setYear(year);

         items.push_back(food);
       }
     }
     while (name != "quit);

I'd like to iterate through the vector of pointers and call the display function for all the items but I am unable to dereference them using iterators.

How would I be able to sucessfully iterate through these pointers and call the display function?

Unfortunately,

vector<Food*>::iterator iter = items.begin();
while (iter < items.end())
{
  cout << *iter->display() << endl;
}

Results in:

error: request for member ‘display’ in ‘* iter.__gnu_cxx::__normal_iterator<_Iterator, _Container>::operator-><Food**, std::vector<Food*> >()’, which is of pointer type ‘Food*’ (maybe you meant to use ‘->’ ?)
   cout << *iter->display() << endl;

Thank you!

Operator Precedence has got you. *iter->display() is interpreted by the compiler as *(iter->display()) because -> has precedence over (will execute before) * . A cleaner way to look at this is *((*iter).display())

  1. Dereference iterator to a Food * .
  2. Attempt to invoke display on the Food* . Fails and results in the compiler error.
  3. Dereference the result of the call to display .

You need to force the execution ordering you want with some brackets: (*iter)->display()

  1. Dereference iterator to a Food *
  2. Dereference again to a Food
  3. Invoke display on the Food

Fixing this leads to problem 2: display doesn't return anything that can be written to cout . Fortunately, display does all the printing that is required.

while (iter < items.end())
{
    (*iter)->display();
}

resolves that problem, but in idiomatic C++ there is a better solution: overload the << operator.

Food picks up a friend function

class Food
{
private:
    string name;
    int month;
    int year;

public:
    void display()
    {
      cout << name << " - " << month << "/" << year << endl;
    }
    friend ostream & operator<<(ostream & out, const Food & food)
    {
        out << food.name << " - " << food.month << "/" << food.year;
        return out;
    }
};

Then you can

vector<Food*>::iterator iter = items.begin();
while (iter < items.end())
{
  cout << **iter << endl;
}

or with a range-based for loop

for (auto & item:items)
{
      cout << *item << endl;
}     

Side note: In addition to practicing pointers, practice Smart Pointers . You'll find them much more useful.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM