操作员的模糊过载>>

时间:2014-02-08 17:52:39

标签: c++ operator-overloading std cin

我开始学习C ++,但我找不到下面错误的原因。这段代码在“Teach Yourself C ++”一书中。

main.cpp:13:错误:'运营商>>'的模糊重载'std :: cin>> (INT)的ip”

#include<iostream>

using namespace std;

enum ignition_parts {distributor=1,cap,points,plug,condenser,coil,wires,done};


 main() {

 ignition_parts ip;
 do{
 cout << "\nInsira no item (1-7, 8 para sair):";
 std::cin >> (int)ip;
 switch(ip){

     case distributor: cout<< "Distribuidor";
     break;

     case cap: cout<< "Tampa";
     break;

     case points: cout << "Pontos";
     break;

     case plug:cout << "Vela";
     break;

     case condenser: cout<<"Condensador";
     break;

     case done: break;

     default: cout << "No item ignorado";
     break;

     }

     } while (ip != done);

}

2 个答案:

答案 0 :(得分:4)

所有重载都同样糟糕;)

    std::cin >> (int&)ip;

将“关闭”因为您无法分配到右值。

然而,

    int tmp;
    std::cin >> tmp;
    ip = static_cast<ignition_parts>(tmp);

代替可移植性/定义的行为

这是一个添加了错误处理的版本,并将ip的输出流提取到其自己的函数中:Coliru上的 See it Live

#include<iostream>

enum ignition_parts {distributor=1,cap,points,plug,condenser,coil,wires,done};

std::ostream& operator<<(std::ostream& os, ignition_parts ip)
{
    switch(ip) {
            case distributor: return os << "Distribuidor";
            case cap:         return os << "Tampa";
            case points:      return os << "Pontos";
            case plug:        return os << "Vela";
            case condenser:   return os << "Condensador";
            default:          return os << "No item ignorado";
    }
    // unreachable
}

int main() {
    ignition_parts ip;
    do {
        std::cout << "\nInsira no item (1-7, 8 para sair): ";

        int tmp;
        if(std::cin >> tmp) 
        {
            ip = static_cast<ignition_parts>(tmp);

            if (ip == done) {
                break;
            }

            std::cout << ip;
        } else {
            if(std::cin.eof()) {
                break;
            }
            std::cout << "Whoops: invalid input\n";
            std::cin.clear();
            std::cin.ignore(1024, '\n');
        }

    } while(std::cin && ip != done);

}

答案 1 :(得分:0)

建议:使用数组作为标识符来转换字符串。

std::ostream& operator<<(std::ostream& os, ignition_parts ip)
{
    static const char * names[] =
    {
       "Nothing",
       "Distribuidor", "Tampa", "Pontos", "Vela", "Condensador"
    }
    // Test ip for validity first.
    os << names[ip];
}

以上情况并不安全,因为如果enum顺序发生变化,上表中的映射将产生错误的结果。此外,如果扩展enum而数组不是,则可能会出现运行时缓冲区溢出错误(讨厌)。

更安全的方法是在表格中包含标识符:

struct Entry
{
    ignition_parts part_id;
    const char *   name;
};
const Entry  name_table[] =
{
  {distributor, "Distribuidor"},
  {cap,         "Tampa"},
  {points,      "Pontos"},
  {plug,        "Vela"},
  {condenser,   "Condensador"},
};
const unsigned number_of_entries =
    sizeof(name_table) / sizeof(name_table[0]);

您在每个条目中搜索匹配的ID,然后返回表条目的name字段。

此方法的一个好处是您可以在不更改代码的情况下添加条目,并且顺序不依赖(条目顺序无关紧要)。