Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Исключительные ситуации в С++. Зачем?!


Автор: Podarochek 23.5.2008, 19:16
Уважаемые. Скажите пожалуйста, что-то не очень с книг я и пойму, зачем эти "исключительные ситуации", разве нельзя обойтись обычной проверкой, например условными операторами? smile

Добавлено через 10 минут и 21 секунду
вот два примера - один с книги(1), один мой(2)smile В чем принципиальная разница. Еще думать о каких-то блоках try и т.д. Я думаю, что не спроста таковое придумано, но нужны фактыsmile

Код


# include <iostream>
using namespace std;

void main(){    
    
    // блок try способный возбудить
    // три исключения 
    try{

        // указатель и размер 
        // динамического массива
        int*ptr=0;
        int size;

        // ввод размера
        cout<<"\nPut size:\n";
        cin>>size;

        // если размер выходит за пределы
        // заданно го диапазона
        if(size<1||size>500)
            // возбуждаем исключение типа char*
            // блок try обрывается
            throw "\n\nErr Size!!!\n\n";

        // иначе создаем массив
        ptr=new int [size];

        // проверяем, выделилась ли память
        if(!ptr)
            // если нет возбуждаем 
            // исключение типа char*
            // блок try обрывается
            throw "\n\nErr Memory!!!\n\n";
        
        // иначе создаем тестовую переменную a
        // осуществляем ввод данных с
        // клавиатуры
        int a;
        cout<<"\nPut digit a:\n";
        cin>>a;

        
        if(a==0)
            // если a равно 0 возбуждаем 
            // исключение типа int
            // блок try обрывается
            throw a;
            

    }

    // отлов всех исключений типа int
    catch(int s){
        cout<<"\nError - A = "<<s<<"\n\n";
    }

    // отлов всех ислючений типа char*
    catch(char*s){
        cout<<s;
    }
    
}


# include <iostream>
using namespace std;

void main(){    
    
        // указатель и размер 
        // динамического массива
        int*ptr=0;
        int size;
        // ввод размера
        cout<<"\nPut size:\n";
        cin>>size;
        // если размер выходит за пределы
        // заданно го диапазона
        if(size<1||size>500)
        {
            cout<<"\n\nErr Size!!!\n\n";
            return;
        }
        // иначе создаем массив
        ptr=new int [size];
        // проверяем, выделилась ли память
        if(!ptr){
            cout<<"\n\nErr Memory!!!\n\n";
            return;
        }
        // иначе создаем тестовую переменную a
        // осуществляем ввод данных с
        // клавиатуры
        int a;
        cout<<"\nPut digit a:\n";
        cin>>a;
        if(a==0){
        cout<<"\nError - A = "<<a<<"\n\n";
        return;
        }
    
}


Автор: mes 23.5.2008, 19:40
Код

class A 
{
     A() {  ch=new char(1000000);  } // если не хватит памяти то что делать?

   private:
     char *ch;
};



Добавлено через 1 минуту и 10 секунд
попробуй применить оба способа и почуствуешь разницу ))

Автор: JackYF 23.5.2008, 19:44
Цитата(Podarochek @  23.5.2008,  18:16 Найти цитируемый пост)
зачем эти "исключительные ситуации"

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

Автор: rrrFer 23.5.2008, 19:55
http://www.citforum.idknet.com/programming/cpp_march/cpp_089.shtml
я вот тоже недавно думал зачем такое придумали...единственное что придумал, что неплохо бы их использовать с классами, чтобы например ошибки некоторой функции класса обрабатывались в одном месте все, а если эта функция конструктор/деструктор, то в одном месте их обработать иначе затруднительно, потому-что конструкторы не возвращают значений.
представляю я это себе так:
Код

class c1{
  public:
    void f1();
  private:
    void realFunction();
}
void c1::f1(){
   try{
      f1();
  }
  catch(){/*обработка ошибок*/}
}
void c1::realFunction(){
  if(что то не так){
    throw ...
  }
  if(что то еще не так){
    throw ...
  }
}

ну я так это себе представляю...

Автор: Podarochek 23.5.2008, 19:57
Цитата(mes @  23.5.2008,  19:40 Найти цитируемый пост)
class A 
{
     A() {  ch=new char(1000000);  } // если не хватит памяти то что делать?

   private:
     char *ch;
};


наверно в конструкторе поставить проверку if(ch){cout<<"Error";exit(0);} или еще раз попытаться выделить
как тут поможет исключение smile 


Цитата(JackYF @  23.5.2008,  19:44 Найти цитируемый пост)
В частности, компилятор даёт тебе гарантию что, исключительная ситуация не может быть пропущена просто так. А ты не можешь дать гарантию, что ты не забудешь в коде проверить возвращённое значение. 

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

Автор: mes 23.5.2008, 20:27
Цитата(Podarochek @  23.5.2008,  19:57 Найти цитируемый пост)
 if(ch){cout<<"Error";exit(0);} 


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

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

Добавлено через 1 минуту и 15 секунд
Цитата(Podarochek @  23.5.2008,  19:57 Найти цитируемый пост)
 ну я же всеравно должен описать исключение, почему же я могу ее тоже не забыть? 

не совсем так... но это позже..

Автор: Podarochek 23.5.2008, 20:54
Цитата(mes @  23.5.2008,  20:27 Найти цитируемый пост)
но когда составляешь класс не знаешь в каком месте проги он будет вызван и как имено надо поступить с такой ошибкой
например программа ворд и в ней открыт важный документ - тут создается класс наш класс.. не хватает памяти .. прога вылетила и ничего не сохранила... теперь представь лицо и радостные возгласы, того кто всю ночь просидел над составлением этого доклада и не успел сохранить. ))


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

Автор: maxim1000 23.5.2008, 20:56
а в приведённом примере исключения и не нужны (детально не изучал - исхожу только из того, что всё в пределах одной функции)

исключения нужны, когда выполнить заказанное действие не получается, а что с этим делать в данном месте непонятно

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

Автор: Rififi 23.5.2008, 21:41
Исключения повышают безопасность программы.

"Если функция сообщает о возникновении исключительной ситуации, устанавливая флаг статуса или возвращая код ошибки, то нет никакой гарантии, что модуль, вызвавший функцию, проверит этот флаг или код возврата. В результате работа программы может продолжиться, невзирая на исключительную ситуацию. Если же функция сообщает об опасной ситуации с помощью исключения, а это исключение не обрабатывается, работа программы тут же прекращается"
© С. Мейерс, "Наиболее эффективное использование C++"

Об исключениях (как и о многом другом) можно прочитать в этой книге.

Автор: jonie 23.5.2008, 23:59
new не генерирует исключений вроде как.

Автор: JackYF 24.5.2008, 00:14
Цитата(jonie @  23.5.2008,  22:59 Найти цитируемый пост)
new не генерирует исключений вроде как. 

По-умолчанию - генерирует.

Автор: jonie 24.5.2008, 13:18
да, действительно bad_alloc возбуждается... но где-то в блогах про никс читал что может и не узнать что нет памяти.... чет такое было... мб путаю.

Автор: Fazil6 24.5.2008, 13:42
Цитата(Podarochek @  23.5.2008,  19:16 Найти цитируемый пост)
 зачем эти "исключительные ситуации", разве нельзя обойтись обычной проверкой, например условными операторами?

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

Автор: mes 24.5.2008, 15:47
Цитата(Fazil6 @  24.5.2008,  13:42 Найти цитируемый пост)
можешь обрабатывать ошибку там где ты ее можешь обработать

там где ты знаешь как ее обработать  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)