在迭代器中取消引用类指针函数 [英] Dereferencing a class pointer function in iterator

查看:80
本文介绍了在迭代器中取消引用类指针函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个指向名为Food的类的指针的矢量

  vector< Food *>项目; 

该类如下所示:

 类Food{私人的:字符串名称;int月年份上市:无效的display(){cout<<名称<<-"<<月<<"/"<<年<<恩德尔}} 

然后我创建了一个提示这些项目的功能

  void hintInventory(vector< Food *>& items){字符串名称;int月年份做{cout<<输入商品名称:";getline(cin,名称);如果(名称!=退出"){cout<<输入到期月份:";cin>>月;cout<<输入到期年份:";cin>>年;cin.ignore();食物*食物=新食物;food-> setName(name);food-> setMonth(month);食物-> setYear(年);items.push_back(food);}}while(name!=退出); 

我想遍历指针的向量并为所有项目调用display函数,但是我无法使用迭代器对其进行取消引用.

我如何能够成功地遍历这些指针并调用显示函数?

不幸的是

  vector< Food *> :: iterator iter = items.begin();一会儿(iter< items.end()){cout<<* iter-> display()<<恩德尔} 

结果:

 错误:在"* iter"中请求成员"display".__gnu_cxx :: __ normal_iterator< _Iterator,_Container> :: operator->< Food **,std :: vector< Food *>>()",其指针类型为食物*"(也许您打算使用->"?)cout<<* iter-> display()<<恩德尔 

谢谢!

解决方案

操作员优先级有你.编译器将 * iter-> display()解释为 *(iter-> display()),因为-> 具有优先于(将在 * 之前执行).一种更清晰的查看方法是 *((* iter).display())

  1. 将迭代器取消引用到 Food * .
  2. 尝试在 Food * 上调用显示.失败并导致编译器错误.
  3. 取消对 display 的调用结果.

您需要在方括号中强制使用所需的执行顺序:(* iter)-> display()

  1. 将迭代器取消引用到 Food *
  2. 再次取消引用 Food
  3. Food
  4. 上调用显示

修复此问题会导致问题2: display 不会返回可写入 cout 的任何内容.幸运的是, display 可以完成所有需要的打印.

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

解决了这个问题,但是在惯用的C ++中,有一个更好的解决方案:重载<< 运算符.

Food 选择一个 friend 函数

 类食品{私人的:字符串名称;int月年份上市:无效的display(){cout<<名称<<-"<<月<<"/"<<年<<恩德尔}朋友ostream&运算符<<(流& out,const Food&food){出<<food.name<<-"<<food.month<<"/"<<食物年退回}}; 

那么您可以

  vector< Food *> :: iterator iter = items.begin();一会儿(iter< items.end()){cout<<** iter<<恩德尔} 

或基于范围的for循环

<自动> <代码>(自动和项目:项目){cout<<*项目<<恩德尔}

旁注:除了练习指针之外,还练习智能指针.您会发现它们更有用.

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.

这篇关于在迭代器中取消引用类指针函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆