C ++ - Куда бросить исключение? - PullRequest
3 голосов
/ 07 июня 2010

У меня есть какой-то идеологический вопрос, поэтому:

Предположим, у меня есть какая-то шаблонная функция

template <typename Stream>
void Foo(Stream& stream, Object& object) { ... }

, которая что-то делает с этими object и stream (например, сериализует этот объект в поток или что-то в этом роде.)

Допустим, я также добавил несколько простых оболочек, таких как (и скажем, числоиз этих оболочек равно 2 или 3):

void FooToFile(const std::string& filename, Object& object)
{
   std::ifstream stream(filename.c_str());
   Foo(stream, object);
}

Итак, мой вопрос:

Где в этом случае (идеологически) я должен выбросить исключение, если мой stream плох?Должен ли я сделать это в каждой оболочке или просто перенести этот чек на мой Foo, чтобы его тело выглядело как

if (!foo.good()) throw (something);
// Perform ordinary actions

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

Спасибо.

Ответы [ 5 ]

5 голосов
/ 07 июня 2010

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

2 голосов
/ 07 июня 2010

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

Чтобы избежать избыточности кода, вызовите обычную функцию, которая делает это исключение / ошибку для вас. Не копируйте / вставляйте код в каждую упаковку.

1 голос
/ 07 июня 2010

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

1 голос
/ 07 июня 2010

Мне нравится использовать вспомогательные функции для этого:

struct StreamException : std::runtime_error
{ 
    StreamException(const std::string& s) : std::runtime_error(s) { }
    virtual ~StreamException() throw() { }
};

void EnsureStreamIsGood(const std::ios& s)
{
    if (!s.good()) { throw StreamException(); }
}

void EnsureStreamNotFail(const std::ios& s)
{
    if (s.fail()) { throw StreamException(); }
}

Я проверяю их непосредственно до и после выполнения потоковых операций, если не ожидаю сбоя.

1 голос
/ 07 июня 2010

Чем раньше вы поймаете исключение, тем лучше. Чем конкретнее исключение - тем лучше. Не бойтесь включать большую часть своего кода в блоки try catch, кроме объявления.

Например:

int count = 0;
bool isTrue = false;
MyCustomerObject someObject = null;

try
{
   // Initialise count, isTrue, someObject. Process.
}
catch(SpecificException e)
{
// Handle and throw up the stack. You don't want to lose the exception.
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...