2014-02-08 96 views
1

我开始学习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); 

} 
+0

你不应该得到多个匹配,你应该没有得到匹配。 – chris

+1

@chris它有很多匹配需要/同样不好/隐式的转换。欢迎来到C++地狱:) – sehe

+0

@sehe,恩,是的。我想说的是,如果编译器发现同样的*好的*匹配,那么编译器就会非常糟糕,从而导致调用不明确。 – chris

回答

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字段。

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

4

所有重载都同样糟糕;)

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

将“关闭”因为您不能分配给右值。

然而,做

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

而不是为便携/定义的行为

下面是添加了错误处理的一个版本,并提取ip输出流到它自己的功能:See it Live上Coliru

#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); 

}