Подтвердить что ты не робот

Исключения С++. Выбрасывает c-строку как исключение?

Я работаю над небольшой программой на С++ и изучаю исключения. Является ли следующий код "плохим", и если да, что я могу сделать, чтобы улучшить его?

try {
    // code
    if (some error) {
        throw "Description of error.";
    }
}
catch (char* errorMessage) {
    cerr << errorMessage << endl << "Fatal error";
}

Есть ли что-то неправильное в том, что вы выбрали массив char как исключение?

EDIT: Будет ли это лучшим способом?

const char errorMessage[] = "Description of error";

try {
    // code
    if (some error) {
        throw errorMessage;
    }
}
catch (char* errorMessage) {
   cerr << errorMessage << endl << "Fatal error";
}
4b9b3361

Ответ 1

Гораздо лучше бросить стандартный объект исключения. В общем, наилучшей практикой является бросить что-то, полученное из std::exception, так что если в какой-то ситуации это приведет к завершению вашей программы, реализация имеет больше шансов распечатать полезную диагностику.

Потому что это не сложно сделать, я бы никогда не рекомендовал бросать строковый литерал.

#include <stdexcept>

void someFunction()
{
    try {
        // code
        if (some error) {
            throw std::runtime_error( "Description of error." );
        }
    }
    catch (const std::exception& ex) {
        std::cerr << ex.what() << "\nFatal error" << std::endl;
    }
}

Ответ 2

Бросок строкового литерала, как правило, является плохой идеей, потому что, по мере развития кода, программистам, возможно, потребуется обогатить сообщение об ошибке дополнительной информацией, например. значение переменной или номер строки, из которой выбрано исключение.

Учитывая неизвестный код клиента, который ловит const char*, программист предложил использовать более динамичный механизм для объединения желаемой информации:

  • a std::string и +
  • a std::ostringstream
  • a char и, возможно, strcat и/или sprintf()

Наиболее очевидные способы их использования не работают или не работают хорошо:

// temporaries...
throw (std::string("couldn't parse input: ") + input).c_str();
throw (std::ostringstream() << "error line " << __LINE__).str().c_str();
char buf[1024]; sprintf(buf, "error line %ld%", __LINE); throw buf;

// not thread-safe
static char buf...

Даже если программист знает, что он не делает ничего из этого, у них все равно будет время найти весь код клиента, который должен начать принимать более богатый тип значения, особенно если другое использование throw/catch const char* сохраняется.

Таким образом, использование класса, встраивающего гибкое описание std::string по значению, очень важно для написания поддерживаемого кода.

Ответ 3

Нет проблем с бросанием массива char. Просто, что вы должны получить как,

catch(const char* const errorMessage) {...}

1st const должен добавить возможность получать любой массив char char* const char* char[] const char[]

2nd const указывает, что errorMessage не предназначен для изменения в блоке catch

Ответ 4

Существует общая проблема неспособности легко фильтровать ваши исключения и действовать на них в зависимости от типа. Тем не менее, я не знаю, есть ли С++ конкретная причина не делать это

Ответ 5

std:: exception (или, по крайней мере, std:: runtime_error) содержит строку, к которой можно получить доступ через метод what(). Самое лучшее, что вы можете сделать, это использовать это, поскольку он стандартный и другой код может его ожидать, и поскольку он все равно служит вашей цели.

В этом случае лучше придерживаться стандарта.

Ответ 6

Если ваша идея выбросить строку в качестве ошибки была для удобства отображения ошибки пользователю, подумайте, что это затруднит локализацию вашего приложения (может или не может быть для вас проблемой).

Также, если другая часть приложения должна понять, что такое ошибка, чтобы она могла реагировать на нее (например, если это ошибка отключения, попробуйте автоматически подключиться, но если это ошибка пароля, просто покажите сообщение об ошибке пользователь), лучше иметь какой-то код ошибки, доступный для ловушки исключения.

В нашем приложении наши исключения получены из std:: exception. Они содержат тип ошибки (перечисление), сообщение об ошибке отладки (включая номер файла/строки) и локализованную строку ошибок.

Ответ 7

Я думаю, это намного проще.:).

#include <iostream>
#include <exception>

using namespace std;

int main() {
    try {
        throw runtime_error("This is an Error"); 
    }catch (exception& e){
        cout << "Exception: " << e.what() << endl; 
    }
    return 0; 
}