2009-06-01 8 views
3

Что такое хороший способ вернуть успех или один или несколько кодов ошибок из C++?как вернуть несколько кодов ошибок из функции C++

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

+0

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

+0

У меня есть эта функция-член, которая называется save(), которая сохраняется для каждой из переменных-членов. Для вызова функции save() есть как минимум десять из этих переменных-членов, я хочу узнать, вызов не удался, и если да, то на какой переменной-члене (некоторые из них жесткие, некоторые из них мягкие). – bob

ответ

7

Вы можете либо вернуть объект с несколькими полями ошибок, либо использовать «out'parameters».

Как вы это сделаете, это зависит от вашего дизайна и того, что именно вы пытаетесь вернуть назад. Обычный сценарий - это когда вам нужно сообщить код состояния вместе с сообщением рода. Иногда это делается, когда функция возвращает код состояния в качестве возвращаемого значения, а затем возвращает статус сообщения через параметр «выход».

Если вы просто возвращаете набор «кодов», может возникнуть смысл построить тип структуры и вернуть это. В этом случае я был бы склонен передавать его в качестве параметра out и иметь внутренний метод обновления, а не каждый раз назначать новый.

Планируете ли вы делать это один или несколько раз?

+0

Объект - прекрасное решение, так как вы можете вернуть практически все, что хотите, например. коды ошибок, строки ошибок и т. д. –

4

Самый простой способ вернуть два значения это с станд :: пары <> Шаблон:

2

Вы должны вернуть их в качестве выходных параметров:

bool function(int& error1, int& error2, stringx& errorText, int& error3); 
2

Я бы использовать bitset если вы» re намерение состоит в том, чтобы чисто возвращать состояния ошибки. например

const bitset<10> a_not_set(1); 
const bitset<10> b_not_set(2); 
const bitset<10> c_not_set(4); 

... 

bitset<10> foo(T& a, T& b, T& c, ...) 
{ 

    bitset<10> error_code = 0; 

    ... 


    if (/* a can't be set */) 
    { 
     error_code |= a_not_set; 
    } 

    ... 

    if (/* b can't be set */) 
    { 
     error_code |= b_not_set; 
    } 

    ... 

    // etc etc 

    return error_code; 
} 

bitset<10> err = foo(a, b, c, ...); 
if (err && a_not_set) 
{ 
    // Blah. 
} 
+0

Маленький и компактный, но не очень читаемый. –

2

Вы можете использовать целое число с бит-манипуляцией (aka flags).

+0

Маленький и компактный, но не очень читаемый. –

+0

Вы, очевидно, используете #define ... –

+0

+1 Хорошая идея для ограниченного количества ошибок, возможно, вы можете расширить свой ответ с помощью некоторого кода ... –

7

Я знаю, что это не реально ответить на ваш вопрос, но ...

В C++ вы должны использовать исключение вместо возврата кодов ошибок. Коды ошибок чаще всего используются библиотеками, которые не хотят заставить пользователя библиотеки использовать конкретное соглашение об обработке ошибок, но на C++ у нас уже есть stdexcept. Конечно, могут быть причины, по которым вы не используете исключения, например, если вы пишете встроенный код или расширения ядра.

+4

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

+0

И класс исключения может содержать всю подробную информацию, которую ОП запрашивал в качестве атрибутов. – lothar

+1

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

0

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

Причины перечислены here, at C++ FAQ lite, и они заключают с:

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

6

Я обычно использую boost::tuple:

typedef boost::tuple<int,int> return_value; 

return_value r = my_function(); 

int first_value = boost::get<0>(r); 
int second_valud = boost::get<1>(r); 

EDIT

Вы также можете использовать boost::tie для извлечения значений из кортежа:

boost::tie(first_value, second_value) = r; 
+1

Вы можете использовать уровни для разгруппировки кортежа: http://www.boost.org/doc/libs/1_39_0/libs/tuple/doc/tuple_users_guide.html#tiers –

+0

Действительно! Добавлено в ответ, спасибо! –

2

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

Если мне действительно нужно придерживаться Retrun-кода ошибки стиля, я бы определить тип eunm для определения ошибок с битовыми операциями ..

enum error 
{ 
    NO_ERROR = 0, 

    MEMBER_0_NOT_SAVED = 1, 
    MEMBER_1_NOT_SAVED = 1 << 1, 
    MEMBER_2_NOT_SAVED = 1 << 2, 
    // etc.. 

}; 

int save() 
{ 
    int ret = NO_ERROR; 

    // fail to save member_0 
    ret |= MEMBER_0_NOT_SAVED; 

    // fail to save member_1 
    ret |= MEMBER_1_NOT_SAVED; 

    // .... 

    return ret; 
} 

int main(void) 
{ 
    int ret = save(); 
    if(ret == NO_ERROR) 
    { 
     // good. 
    } 
    else 
    { 
     if(ret & MEMBER_0_NOT_SAVED) 
     { 
       // do something 
     } 

     if(ret & MEMBER_1_NOT_SAVED) 
     { 
       // do something 
     } 

     // check the other errors... 
    } 
} 

Это просто грубый пример. Лучше поместить это в класс или использовать пространство имен.

Смежные вопросы