Простейший способ сообщения об ошибках предполагает использование возвращаемого значения функции или метода. Функция сохранения объекта в базе данных может возвращать логическое значение: true в случае успешного сохранения, false – в случае ошибки.
class Database{public: bool SaveObject(const Object&obj);};Соответственно, вызов метода должен выглядеть так:if (database.SaveObject(my_obj) == false ){ //обработка ошибки} Обработка ошибки, разумеется, зависит от конкретной программы. Типична ситуация, когда при многократно вложенных вызовах функций обработка происходит на несколько уровней выше, чем уровень, где ошибка произошла. В таком случае результат, сигнализирующий об ошибке, придется передавать во всех вложенных вызовах.
int main(){ if (fun1()==false ) //обработка ошибки return 1;}boolfun1(){ if (fun2()==false ) return false ; return true ;}boolfun2(){ if (database.SaveObject(obj)==false ) return false ; return true ;} Если функция или метод должны возвращать какую-то величину в качестве результата, то особое, недопустимое, значение этой величины используется в качестве признака ошибки. Если метод возвращает указатель, выдача нулевого указателя применяется в качестве признака ошибки. Если функция вычисляет положительное число, возврат - 1 можно использовать в качестве признака ошибки.
Иногда невозможно вернуть признак ошибки в качестве возвращаемого значения. Примером является конструктор объекта, который не может вернуть значение. Как же сообщить о том, что во время инициализации объекта что-то было не так?
Распространенным решением является дополнительный атрибут объекта – флаг, отражающий состояние объекта. Предположим, конструктор класса Database должен соединиться с сервером базы данных.
class Database{public : Database(const char *serverName); ... bool Ok(void )const {return okFlag;};private : bool okFlag;};Database::Database(const char*serverName){ if (connect(serverName)==true ) okFlag =true ; else okFlag =false ;}int main(){ Database database("db-server"); if (!database.Ok()){ cerr <<"Ошибка соединения с базой данных"<<endl; return 0; } return 1;} Лучше вместо метода Ok, возвращающего значение флага okFlag, переопределить операцию ! (отрицание).
class Database{public : bool operator !()const {return !okFlag;};}; Тогда проверка успешности соединения с базой данных будет выглядеть так:
if (!database){ cerr <<"Ошибка соединения с базой данных"<<endl;} Следует отметить, что лучше избегать такого построения классов, при котором возможны ошибки в конструкторе. Из конструктора можно выделить соединение с сервером базы данных в отдельный метод Open :
class Database{public : Database(); bool Open(const char*serverName);} и тогда отпадает необходимость в операции ! или методе Ok().
Использование возвращаемого значения в качестве признака ошибки – метод почти универсальный. Он применяется, прежде всего, для обработки запланированных ошибочных ситуаций. Этот метод имеет ряд недостатков. Во-первых, приходится передавать признак ошибки через вложенные вызовы функций. Во-вторых, возникают неудобства, если метод или функция уже возвращают значение, и приходится либо модифицировать интерфейс, либо придумывать специальное "ошибочное" значение. В-третьих, логика программы оказывается запутанной из-за сплошных условных операторов if с проверкой на ошибочное значение.