2016-04-14 2 views
0

Я создаю обычную хеш-таблицу на основе линейного зондирования в C++ 11, в которой я создал функцию get(). Функция должна возвращать значение, соответствующее ключу в хеш-таблице. Это мой код:Как выбросить исключение, когда в функции не возвращается значение?

template<class Key, class Value>  
Value OpenMap<Key,Value>::get(const Key& k){ 
    int index = hash(k); 
    int i = index; 
    do{ 
     if(buff[i].empty) 
      break; 
     if(buff[i].elem.key==k) 
      return buff[i].elem.value; 
     i = (i+1)%capacity; 
    }while(i!=index); 
} 

Проблема в том, что каждый переданный ключ может не иметь соответствующего значения в хэш-таблице. В этой функции я не могу понять, как справиться с этим исключением. Каковы возможные способы устранения этого исключения и как это работает C++ STL unordered_map<>?

+0

[ 'станд :: unordered_map'] (http://en.cppreference.com/w/cpp/container/unordered_map) решает эту проблему путем создания * * запись в таблице. Если вы используете оператор индексирования (['operator []'] (http://en.cppreference.com/w/cpp/container/unordered_map/operator_at), чтобы получить элемент с карты, а ключ не существует, тогда запись создается по умолчанию - построение значения. Затем возвращается вновь построенное значение. –

+0

@JoachimPileborg Да, но это то, что делает 'operator []'. В моем коде у меня также есть аналогичная функция, которая добавляется в случае, если нет значения соответствующего ключа. Но мне нужно обработать исключение в этой функции 'get (Key)'. –

+0

Хорошо, я понимаю. В этом случае 'std :: unodered_map' имеет дело с ним, не имея прямой функции' get' вообще. Вместо этого у него есть функция ['find'] (http://en.cppreference.com/w/cpp/container/unordered_map/find), которая возвращает итератор. Поэтому он просто борется с вашей проблемой, избегая этого. –

ответ

0

Вы можете throw исключение, когда не найдено никакого значения, то в вашем коде, вы окружаете get(...) с try-catch заявления

class MyException{ 
    // ordinary class 
} 

template<class Key, class Value>  
Value OpenMap<Key,Value>::get(const Key& k){ 
    int index = hash(k); 
    int i = index; 
    do{ 
     if(buff[i].empty) 
      break; 
     if(buff[i].elem.key==k) 
      return buff[i].elem.value; 
     i = (i+1)%capacity; 
    }while(i!=index); 
    throw MyException(); 
} 

... 
OpenMap<int, int> myMap; 
try{ 
    int value = myMap.get(10); 
}catch(MyException & ex){ 
    // do whatever you want witn ex 
} 
... 

отмечает, что MyException является обычным классом, так что он может иметь конструктор и методы для Например, вы можете передать key в качестве параметра, а затем распечатать сообщение, чтобы этот ключ не был найден.

0

Я бы выбрал std::invalid_argument, хотя std::domain_error и std::out_of_range также имеет смысл.

Вызывающий абонент просто поймал бы std::exception.

0

Вы можете рассмотреть optional. Он находится в стандарте C++ 17 link. Вы можете использовать boost :: optional на данный момент. Значение optional может быть проверено на значение, и .get() можно назвать, если оно имеет значение. Значение может быть переопределено в любое время и также может быть доступно как указатель.

template<class Key, class Value>  
boost::optional<Value> OpenMap<Key,Value>::get(const Key& k){ 
    int index = hash(k); 
    int i = index; 
    do{ 
     if(buff[i].empty) 
      break; 
     if(buff[i].elem.key==k) 
      return buff[i].elem.value; 
     i = (i+1)%capacity; 
    }while(i!=index); 
    return boost::none; // empty optional 
}