2013-06-28 2 views
0

У меня возникают проблемы с исключениями в C++, включающие структуру исключений и способы передачи аргументов и многое другое.Проблема с C++ с исключениями

С этой страницы: http://www.cplusplus.com/doc/tutorial/exceptions/

1) Когда вы бросаете что-то, например: throw 20;, вы проходя 20 к int e, и если да, то какой смысл бросать целое, чтобы поймать, если вы только ответить на набрав команду, чтобы дать экран?

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

3) Глядя на стандартном разделе исключений: являются исключениями, показанного в нижней части (bad_alloc, bad_cast, bad_exception, ... и т.д.) должен быть типа исключений, которые могут быть переданы в переменную? Как вы скажете catch(bad_exception& e), и единственное, что может получить e, это число/float/character, которое не подходит для каких-либо других типов исключений? Честно говоря, меня очень путают со стандартными исключениями.

4) В стандартных исключениях, опять же, есть exceptions в class myexception: public exception конструктор?

Извините за длинный пост. Приветствуются любые онлайн-уроки, чтобы упростить тему, советы или помощь. Спасибо :)

+2

Ваше сообщение предполагает, что вы еще не совсем поняли понятия _type_ (и _class_), _object_ и _variable_. Я бы работал над этим, прежде чем пытаться понять, как работают исключения. –

ответ

3

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

A throw заявление не является неотложной функцией вызова. Это точка в программе, где построен определенный объект (будь то int, std::exception, std::runtime_error, или любой другого типа объекта).

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

Иллюстративный пример:

#include <iostream> 
#include <memory> 
#include <string> 

class my_exception 
{ 
public: 
    my_exception(const std::string& message) : message(message) {} 
    const std::string& what() { return message; } 
private: 
    const std::string message; 
}; 

void boo() 
{ 
    int local = 5; // local, "automatic storage duration" variable 
    throw my_exception("boo threw"); 
} 
void bam() 
{ 
    int* i = new int(42); // dynamically allocated int, unowned, accessible 
    std::unique_ptr<int> j(new int(43)); // dynamically allocated int, owned by a smart pointer with automatic storage duration 
    boo(); 
    delete i; 
} 

void f() 
{ 
    try 
    { 
    bam(); 
    } 
    catch(const my_exception& e) 
    { 
    std::cout << e.what(); 
    } 
} 

int main() 
{ 
    f(); 
} 

Процесс, который потеет заключается в следующем:

  1. main вводится
  2. f() называется
  3. try блок вводится
  4. bam() является с alled
  5. a int динамически выделяется.Создан указатель на int с именем i с автоматической продолжительностью хранения (в стеке)
  6. a unique_ptr объект, содержащий указатель на другой динамически выделенный int.
  7. boo()
  8. int с автоматическим хранением в строении.
  9. Объект типа my_exception построен и начинается раскручивание штанов.
  10. boo() остается, и local разрушается (очистке)
  11. мы вернулись в bam(), а также оставив позади: первый j деструктор «s называется, которая вызывает delete на целое число со значением 43. Затем объект-указатель i разрушен, но целым числом, на которое он указал, не является delete. D. У нас есть утечка памяти (утверждение delete i; никогда не было достигнуто).
  12. мы вернулись в f(), где дружественный catch ловит наш my_exception и выводит message, хотя std::cout.

Чтобы ответить на ваши вопросы:

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

2) См. Выше.

3) A catch «получает» объект. Он работает так же, как функциональные перегрузки. Лучший из них выбран. Если нет совпадения, разматывание продолжается. e ничего не получает. Он может быть сконструирован из того, что выбрано, но для этого требуется, чтобы тип e имел правильное преобразование/конструктор.

4) Нет. Указывает наследование. Пример:

#include <stdexcept> 

class my_exception : public std::exception 
{ 
public: 
    my_exception(const std::string& message) : std::exception(message) {} 
} 

Этот my_exception класс наследует функцию what(), определенный в std::exception, поэтому мне не нужно, чтобы определить это сам.

+0

+1 Мне очень нравится пример! – arne

+0

@ rubenvb Честно говоря, я не понимаю, как стека разматывать вообще. И то, как оцениваются исключения, еще более сбивает меня с толку. Я нахожусь на начальных этапах C++. Поэтому, если вы могли бы указать мне место, где это упрощено, это было бы здорово. У меня много вопросов, и я чувствую, что вопросы, которые у меня есть, намного превысят количество символов, которые мне разрешено печатать. –

+0

@TranslucentDragon Поиск о стеке (не структуре данных), вызов функции в C/C++. Это важный механизм, который вам нужно понять в один прекрасный день. –