2014-02-08 140 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); 

}