簡體   English   中英

操作員的模棱兩可的過載>>

[英]Ambiguous overload for operator>>

我開始學習C ++,但找不到下面的錯誤原因。 這段代碼在《自學C ++》一書中。

main.cpp:13:錯誤:'std :: cin >>(int)ip'中'operator >>'的模棱兩可的重載

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

}

所有重載都同樣糟糕;)

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

將為“關閉”,因為您無法分配給右值。

但是,做

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

代替可移植性/定義的行為

這是一個添加了錯誤處理的版本,並將ip的輸出流提取到它自己的函數中:在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);

}

建議:使用數組作為標識符進行字符串轉換。

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

此方法的一個好處是您可以添加條目而無需更改代碼,並且順序不依賴(條目的順序無關緊要)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM