Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Gwini
10 / 10 / 3
Регистрация: 08.03.2014
Сообщений: 70
#1

Работает ли указатель на базовый класс исключения, когда попадает в блок catch - C++

06.08.2014, 04:04. Просмотров 814. Ответов 18
Метки нет (Все метки)

Работает ли указатель на базовый класс исключения, когда попадает в блок catch так же как обычно? То есть, если есть переопределенные вирутальные методы, то искользуется ли нужный?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.08.2014, 04:04
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Работает ли указатель на базовый класс исключения, когда попадает в блок catch (C++):

Как передать управление в блок catch после системного исключения (компилятор g++)? - C++
Вот пример: не удаётся это сделать #include <windows.h> #include <stdio.h> //Эта функция- НОВЫЙ обработчик...

Указатель на базовый класс - C++
Есть базовый класс и два производных. Так же имеется очередь, в которой хранится как указатели набазовый класс, так и на его наследники. ...

Указатель на базовый класс и на производный - C++
Пытаюсь разобраться с классами и наследованием. Сама эта задача из Дейтела "Как программировать на C++" Есть базовый класс Точка и у...

Иерархия классов и указатель на базовый класс - C++
Существует три класса, один наследуется от другого: class Base { public: virtual int WhoAmI const { return 0; }

Указатель на базовый класс и дружественные функции - C++
Здравствуйте. У меня есть базовый класс Number-простое целое число типа long int. В классе имеется 2 дружественных функции, перегрузка...

Виртуальное наследование (указатель на базовый класс) - C++
У меня ромбическая иерархия классов, при попытке вызвать метод производного класса ошибка, что я не так делаю? Вот исходный код ...

18
__SOKOL__
3 / 3 / 0
Регистрация: 29.06.2013
Сообщений: 107
06.08.2014, 04:26 #2
Ты вот это имеешь ввиду?
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <string>
#include <windows.h>
 
using namespace std;
 
 
class A
{
public:
    virtual void test() { cout << "class A" << endl; }
};
 
class B : public A
{
    virtual void test() override { cout << "class B" << endl; }
};
 
int main()
{
    
    try
    {
        B* b = new B;
        throw b;
    }
    catch(A* a)
    {
        a->test();
        delete a;
    }
    
    return 0;
}

Это работает, срабатывает переопределённый метод.
0
Gwini
10 / 10 / 3
Регистрация: 08.03.2014
Сообщений: 70
06.08.2014, 04:39  [ТС] #3
Немного другое.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// exc_mean.h  -- exception classes for hmean(), gmean()
#include <iostream>
 
class base_excep: public std::logic_error 
{
private:
    double a;
    double b;
public:
    base_excep(double val1 = 0, double val2 = 0, const char* s = "Unknow exception") :a(val1), b(val2), logic_error(s) {}
    virtual ~base_excep() {}
    void what_arg() const { std::cout << "Arguments: " << a << " " << b << std::endl; }
};
 
class bad_hmean: public base_excep
{
private:
    const char* str;
public:
    bad_hmean(double val1 = 0, double val2 = 0, const char* s = "Function: hmean(). Invalid arguments: a = -b\n") : str(s), base_excep(val1, val2, s) {}
};
 
class bad_gmean :public base_excep
{
private:
    const char* str;
public:
    bad_gmean(double val1 = 0, double val2 = 0, const char* s = "Funtion: gmean(). Arguments should be >= 0\n") : str(s), base_excep(val1, val2, s) {}
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//error4.cpp – using exception classes
#include <iostream>
#include <cmath> // or math.h, unix users may need -lm flag
#include "exc_mean.h"
// function prototypes
double hmean(double a, double b);
double gmean(double a, double b);
int main()
{
    using std::cout;
    using std::cin;
    using std::endl;
    
    double x, y, z;
 
    cout << "Enter two numbers: ";
    while (cin >> x >> y)
    {
        try {                  // start of try block
            z = hmean(x,y);
            cout << "Harmonic mean of " << x << " and " << y
                << " is " << z << endl;
            cout << "Geometric mean of " << x << " and " << y
                << " is " << gmean(x,y) << endl;
            cout << "Enter next set of numbers <q to quit>: ";
        }// end of try block               
        catch (base_excep* excep) 
        {
            cout << excep->what();
            excep->what_arg();
            cout << "Sorry, you don't get to play any more.\n";
            break;
        } // end of catch block
    }
    cout << "Bye!\n";
    return 0;
}
 
double hmean(double a, double b)
{
    if (a == -b)
        throw &bad_hmean(a,b);
    return 2.0 * a * b / (a + b);
}
 
double gmean(double a, double b)
{
    if (a < 0 || b < 0)
        throw &bad_gmean(a,b);
    return std::sqrt(a * b); 
}
Тут вызывается what() со строкой определенной в logic_eror. В случае ссылки все хорошо.
0
0x10
2465 / 1637 / 239
Регистрация: 24.11.2012
Сообщений: 4,037
06.08.2014, 05:06 #4
Gwini, а Вы какого результата ожидаете, пытаясь брать адрес временного объекта?
0
Gwini
10 / 10 / 3
Регистрация: 08.03.2014
Сообщений: 70
06.08.2014, 05:09  [ТС] #5
Цитата Сообщение от 0x10 Посмотреть сообщение
Gwini, а Вы какого результаат ожидаете, пытаясь брать адрес временного объекта?
можно поподробнее?
0
0x10
2465 / 1637 / 239
Регистрация: 24.11.2012
Сообщений: 4,037
06.08.2014, 05:11 #6
Gwini, в 42 и 49 строках создается временный объект, у которого нельзя взять адрес, ибо он rvalue. По логике пример даже скомпилироваться не должен.
0
Gwini
10 / 10 / 3
Регистрация: 08.03.2014
Сообщений: 70
06.08.2014, 05:16  [ТС] #7
Цитата Сообщение от 0x10 Посмотреть сообщение
в 42 и 49 строках создается временный объект, у которого нельзя взять адрес, ибо он rvalue. По логике пример даже скомпилироваться не должен.
но все же компилируется. Ссылка работает, как я понимаю, из за того что создается копия согласно механизму исключений. Какие вообще правила действуют к указателям, а то в книжке которую я читаю есть только про ссылки.
0
0x10
2465 / 1637 / 239
Регистрация: 24.11.2012
Сообщений: 4,037
06.08.2014, 05:20 #8
Цитата Сообщение от Gwini Посмотреть сообщение
Ссылка работает, как я понимаю, из за того что создается копия
Ссылки используют как раз чтобы объект исключения лишний раз не копировался.
Можно думать об обработчике catch как о функции - передача аргументов аналогичная.

Добавлено через 2 минуты
Цитата Сообщение от Gwini Посмотреть сообщение
но все же компилируется
Чем?
0
MrCold
855 / 753 / 71
Регистрация: 11.01.2012
Сообщений: 1,942
06.08.2014, 05:21 #9
Gwini,
имеется ввиду ссылка здесь
C++
1
catch (base_excep & excep)
Добавлено через 57 секунд
или через new исключение бросить
0
Gwini
10 / 10 / 3
Регистрация: 08.03.2014
Сообщений: 70
06.08.2014, 05:24  [ТС] #10
Цитата Сообщение от 0x10 Посмотреть сообщение
Ссылки используют как раз чтобы объект исключения лишний раз не копировался
Как это? Прата пишет что объект копируется в любом случае. И по вашей логике если это временный объект то тогда не на что и ссылатся.

Добавлено через 1 минуту
Цитата Сообщение от 0x10 Посмотреть сообщение
Чем?
Visual Studio
0
0x10
2465 / 1637 / 239
Регистрация: 24.11.2012
Сообщений: 4,037
06.08.2014, 05:27 #11
Gwini, пример для иллюстрации:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
 
struct MyException {
    MyException() {
        std::cout << "default ctor" << std::endl;
    }
 
    MyException(const MyException& ex) {
        std::cout << "copy ctor" << std::endl;
    }
};
 
int main() {
    std::cout << "catch by value" << std::endl;
 
    try {
        throw MyException();
    } catch (MyException ex) {
        std::cout << "catch\n" << std::endl;
    }
 
    std::cout << "catch by cref" << std::endl;
 
    try {
        throw MyException();
    } catch (const MyException& ex) {
        std::cout << "catch" << std::endl;
    }
}
Вывод:
Код
$ ./a.out
catch by value
default ctor
copy ctor
catch

catch by cref
default ctor
catch
1
Gwini
10 / 10 / 3
Регистрация: 08.03.2014
Сообщений: 70
06.08.2014, 05:50  [ТС] #12
Я наверное чего то не понимаю, но все же на что тогда ссылатся если объект временный? И как поннимать написаное в книге?
0
Миниатюры
Работает ли указатель на базовый класс исключения, когда попадает в блок catch  
CyberSolver
101 / 74 / 17
Регистрация: 23.07.2014
Сообщений: 686
Записей в блоге: 1
06.08.2014, 06:56 #13
Gwini, g++ это даже не скомпилировал:
Код
In file included from error4.cpp:4:0:
exc_mean.h:12:13: error: looser throw specifier for ‘virtual base_excep::~base_excep()’
     virtual ~base_excep() {}
             ^
In file included from exc_mean.h:3:0,
                 from error4.cpp:4:
/usr/include/c++/4.8/stdexcept:64:13: error:   overriding ‘virtual std::logic_error::~logic_error() throw ()’
     virtual ~logic_error() _GLIBCXX_USE_NOEXCEPT;
             ^
error4.cpp: In function ‘double hmean(double, double)’:
error4.cpp:42:29: error: taking address of temporary [-fpermissive]
         throw &bad_hmean(a,b);
                             ^
error4.cpp: In function ‘double gmean(double, double)’:
error4.cpp:49:29: error: taking address of temporary [-fpermissive]
         throw &bad_gmean(a,b);
Плюс вы нарушаете правило «используй только константные ссылки для исключений». Если бы вы бросили исключение через new — это ещё ладно, хотя тоже плохо. Но вы используете ссылку на локальный объект, т.е. объект на стеке. При обработке исключения стек раскручивается, локальные объекты уничтожаются — т.е. даже если бы ваш код скомпилировался, вы получите указатель на мусор.
0
0x10
2465 / 1637 / 239
Регистрация: 24.11.2012
Сообщений: 4,037
06.08.2014, 07:26 #14
Цитата Сообщение от Gwini Посмотреть сообщение
Я наверное чего то не понимаю, но все же на что тогда ссылатся если объект временный?
Попробую описать по рабоче-крестьянски, не претендуя на точность в формулировках.

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

Далее перехватить этот объект можно по значению - тогда будет создана еще одна копия, а можно по ссылке - тогда лишнего копирования не будет, что и показывает пример в посте 11.
0
Jupiter
Каратель
Эксперт С++
6556 / 3977 / 227
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
06.08.2014, 11:29 #15
Цитата Сообщение от 0x10 Посмотреть сообщение
а можно по ссылке - тогда лишнего копирования не будет, что и показывает пример в посте 11.
эээ...ну тут уж смотря чем и как компилировать
http://codepad.org/MbpfRkH3
1
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.08.2014, 11:29
Привет! Вот еще темы с ответами:

Создание объекта через указатель на базовый абстрактный класс - C++
Есть абстрактный класс, от него наследуется 3 класса. В программе предусмотрено создание нового объекта(добавление клиента страховой...

Вызов виртуальной функции через указатель на базовый класс - C++
Всем привет! Помогите пожалуйста разобраться с вызовом виртуальной функции в программе. В моей программе требуется организовать класс...

Передача в контейнер объекта через указатель на базовый класс - C++
Передаю в stl контейнер list указатель на производный класс, предварительно приведя его к типу производного класса - программа вылетает.В...

Возможно ли вызвать метод наследника через указатель на базовый класс - C++
Возможно ли вызвать метод наследника,через указатель на базовый класс, если он не определён как виртуальный или этого метода просто нет в...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Yandex
Объявления
06.08.2014, 11:29
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru