Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Прогр_на_ЯВУ (Cpp)_-_Лекции.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
882.69 Кб
Скачать

17.2 Возвращаемое значение как признак ошибки

Простейший способ сообщения об ошибках предполагает использование возвращаемого значения функции или метода. Функция сохранения объекта в базе данных может возвращать логическое значение: true в случае успешного сохранения, false – в случае ошибки.

class Database

{

public:

bool SaveObject(const Object&obj);

};

Соответственно, вызов метода должен выглядеть так:

if (database.SaveObject(my_obj) == false ){

//обработка ошибки

}

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

int main()

{

if (fun1()==false ) //обработка ошибки

return 1;

}

bool

fun1()

{

if (fun2()==false )

return false ;

return true ;

}

bool

fun2()

{

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 с проверкой на ошибочное значение.