Closed richelbilderbeek closed 1 year ago
It should not be possible to ignore an error because that could leave the system or a computation in an undefined (or unexpected) state. This is a major source of errors. Example
int printf(const char* ...); // bad: return negative number if output fails
template<class F, class ...Args>
// good: throw system_error if unable to start the new thread
explicit thread(F&& f, Args&&... args);
Simpler examples:
// bad: return negative number if output fails
int say_hello(const std::string& name)
{
if (name.size() == 0) return 1;
std::cout << "Hello " << name << '\n';
}
// good: throw std::logic_error if string is invalid
void say_hello(const std::string& name)
{
if (name.size() == 0) throw std::logic_error("A name has at least one character");
std::cout << "Hello " << name << '\n';
}
// maybe superior: the class 'name' has already checked that the name is at least one character
void say_hello(const name& n) noexcept
{
std::cout << "Hello " << name << '\n';
}
Example in our code:
// Current
void game::eat_food(food& f)
{
if(f.is_eaten())
{
throw std::logic_error("You cannot eat food that already has been eaten!");
}
f.set_food_state(food_state::eaten);
f.reset_timer();
}
// Alternative
void game::eat_food(food& f)
{
assert(!f.is_eaten());
f.set_food_state(food_state::eaten);
f.reset_timer();
}
Q: When to use exceptions? A: When you want to test a function to fail:
// (123) say_hello detect an empty name
{
bool has_thrown{false};
try
{
say_hello("");
}
catch (const std::logic_error& e)
{
has_thrown = true;
}
assert(has_thrown);
}
Done!
noexcept or polymorhism?