Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.60/5: Рейтинг темы: голосов - 5, средняя оценка - 4.60
0 / 0 / 0
Регистрация: 22.11.2020
Сообщений: 42

Объект ошибки для выброса исключения

04.05.2021, 13:55. Показов 1027. Ответов 12

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

Реализация #1:
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
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <iterator>
#include <codecvt>
 
using namespace std;
 
class Error {
    wstring message;
public:
 
    explicit Error(const wstring &mess) noexcept: message{mess} {}
 
    void showMessage() const noexcept {
        wcerr << L"Произошло исключение:" << endl << message << endl;
    }
 
};
 
/** -*- -*- -*- Клиентский код -*- -*- -*- */
 
int main() {
    setlocale(LC_ALL, "Russian");
    try {
        string path{"t12.txt"};
        wifstream inF{path};
        inF.imbue(locale{locale{""}, new codecvt_utf8_utf16<wchar_t>});
        if (!inF) throw Error{L"Файл не был открыт"};
    } catch (const Error &error) {
        error.showMessage();
    }
    system("pause");
    return 0;
}
Что мешает остановиться на таком решении:
Я всё-таки бы хотел уточнить по какому пути не был открыт файл.
Как на зло нельзя передать в wifstream inF{path}; path типа wstring, только char * или string... ужас(
Я не могу конкатенировать wstring с string.

Но хотелось бы такой результат:
C++
1
if (!inF) throw Error {L"Файл по пути " + path + " не был открыт"};
Или хотябы такой (как-нибудь с кортежами):
C++
1
if (!inF) throw Error {L"Файл по пути ", path, " не был открыт"};
Что я придумал:
Я задаю этот вопрос тут, потому что считаю, что моё решение сделать класс Error крайне ужасным, плюс к тому мне кажется что это велосипед и в STL должен быть класс, который как раз предназначен выброса исключений с многобайтовыми сообщениями (wchar_t, wstring), но я не знаю их и к сожалению не нашёл.

Реализация #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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <iterator>
#include <codecvt>
 
using namespace std;
 
class Error {
    wstring wMessage;
    string message;
public:
 
    explicit Error(const wstring &mess) noexcept: wMessage{mess} {}
 
    explicit Error(const string &mess) noexcept: message{mess} {}
 
    Error &add(const string &mess) noexcept {
        message += mess;
        return *this;
    }
 
    Error &add(const wstring &mess) noexcept {
        wMessage += mess;
        return *this;
    }
 
    void showMessage() const noexcept {
        wcerr << L"Произошло исключение:" << endl << wMessage << endl;
        cerr << message << endl;
    }
 
};
 
/** -*- -*- -*- Клиентский код -*- -*- -*- */
 
int main() {
    setlocale(LC_ALL, "Russian");
    try {
        string path{"t12.txt"};
        wifstream inF{path};
        inF.imbue(locale{locale{""}, new codecvt_utf8_utf16<wchar_t>});
        if (!inF) throw Error{L"Файл не был открыт"}.add(path); /// метод add(string) какой кошмар !
    } catch (const Error &error) {
        error.showMessage();
    }
    system("pause");
    return 0;
}
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
04.05.2021, 13:55
Ответы с готовыми решениями:

QML. Аналог this для выброса указателя на себя (QObject) во внешний мир на С++
Есть в QML аналог this, чтоб я мог в какую - то функцию в качестве параметра передать указатель на собственную инстанцию ?

Указатель объект на объект (фикс ошибки)
/*Есть некий объект ObjectOne который содержит в private: такую строку*/ ObjectTwo *obj = new ObjectTwo(); /*При выводе на экран...

ошибки и исключения
Прописан путь к файлу но его может не оказатся там или к нему нет доступа в этом случае в vb вылазит ошибка и прога закрывается. Как...

12
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
04.05.2021, 15:40
Цитата Сообщение от sadomazo228 Посмотреть сообщение
нельзя передать в wifstream inF{path}; path типа wstring
А ты проверял? В VS можно.
0
 Аватар для eva2326
1673 / 501 / 107
Регистрация: 17.05.2015
Сообщений: 1,519
04.05.2021, 16:28
Цитата Сообщение от sadomazo228 Посмотреть сообщение
explicit Error(const wstring &mess) noexcept: message{mess} {}
Здесь дефект: при конструировании messages может вылететь исключение.
Если из функции-noexcept вылетит эксепшен, тогда сработает terminated

Правильно писать:
C++
1
explicit Error(wstring mess) noexcept: message(std::move(mess)) {}
Обратите внимание: конструктор с параметров по значению.
Не по ссылке.

Цитата Сообщение от sadomazo228 Посмотреть сообщение
void showMessage() const noexcept {
        wcerr << L"Произошло исключение:" << endl << message << endl;
    }
Здесь аналогичный дефект: в общем случае wcerr может бросить исключение.

Цитата Сообщение от sadomazo228 Посмотреть сообщение
new codecvt_utf8_utf16<wchar_t>}
Их же вроде бы признали deprecated и удалили из с++17 ?

Цитата Сообщение от sadomazo228 Посмотреть сообщение
Как на зло нельзя передать в wifstream inF{path}; path типа wstring,
Это locale-specific behavior
Компиляторы могут поддерживать, но не обязаны этого делать.

Цитата Сообщение от sadomazo228 Посмотреть сообщение
не кажется что это велосипед и в STL должен быть класс, который как раз предназначен выброса исключений с многобайтовыми сообщениями (wchar_t, wstring)
Все, что касается национальных символов - locale-specific behavior.


---
А вообще, если делать правильно, то ваш класс exception должен быть наследником std::exception.
И при этом он должен быть "реерентабельным".

"реерентабельным" - значит он должен удовлетворять требованиям к обработчикам сигналов.
Например: не использовать кучу (никаких динамических аллокаций).

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


Например:

C++
1
2
...
throw std::runtime_error("file not found:" + filename);
Проблема вышеприведенного фрагмента в том, что на этапе создания диагностического сообщения может вылетить std::bad_alloc, который замаскирует предыдущую проблему.

Вместо std::runtime_error, вы можете использовать свой собственный класс эксепшенов:
C++
1
2
...
throw custom_error("file not found:", filename);
Который использует например... thread_local чаровый буфер, в котором он склеивает все переданные ему в аргументах текстовые сообщения.

Такая мера позволяет сделать надежный класс, который не использует кучу.
И который может прозрачно для вызывающего кода выполнять преобразования между строками, основанными на char/wchar_t
0
Мозгоправ
 Аватар для L0M
1745 / 1039 / 468
Регистрация: 01.10.2018
Сообщений: 2,138
Записей в блоге: 2
04.05.2021, 16:36
Цитата Сообщение от eva2326 Посмотреть сообщение
Правильно писать:
C++
1
explicit Error(wstring mess) noexcept: message(std::move(mess)) {}
Обратите внимание: конструктор с параметров по значению.
Вы считаете, что при создании временного объекта типа wstring при передаче по значению исключение вылететь не может?
0
Любитель чаепитий
 Аватар для GbaLog-
3745 / 1801 / 566
Регистрация: 24.08.2014
Сообщений: 6,020
Записей в блоге: 1
04.05.2021, 16:42
Цитата Сообщение от L0M Посмотреть сообщение
Вы считаете, что при создании временного объекта типа wstring при передаче по значению исключение вылететь не может?
объект конструируется до попадания в тело конструктора.
у std::wstring конструктор перемещения noexcept, так что всё тут ок.
0
 Аватар для eva2326
1673 / 501 / 107
Регистрация: 17.05.2015
Сообщений: 1,519
04.05.2021, 18:16
Цитата Сообщение от L0M Посмотреть сообщение
Вы считаете, что при создании временного объекта типа wstring при передаче по значению исключение вылететь не может?
Я так не считаю))
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
04.05.2021, 18:36
Цитата Сообщение от GbaLog- Посмотреть сообщение
объект конструируется до попадания в тело конструктора.
у std::wstring конструктор перемещения noexcept, так что всё тут ок.
Не совсем. Не важно, где возникнет ошибка - до вызова конструктора, или внутри него - в любом случае ты получишь совсем другое исключение, а не то, что вызывал. Это не очень хорошо.
0
Любитель чаепитий
 Аватар для GbaLog-
3745 / 1801 / 566
Регистрация: 24.08.2014
Сообщений: 6,020
Записей в блоге: 1
04.05.2021, 20:34
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Не совсем. Не важно, где возникнет ошибка - до вызова конструктора, или внутри него - в любом случае ты получишь совсем другое исключение, а не то, что вызывал. Это не очень хорошо.
не понял, что ты имеешь ввиду под другим исключением.
0
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
04.05.2021, 21:36
Наверное, что не появится никаких других между throw и catch.

А для чего вообще делать noexcept для класса исключения? Вроде бы нет такого требования, если не делать наследование от std::exception.
0
 Аватар для eva2326
1673 / 501 / 107
Регистрация: 17.05.2015
Сообщений: 1,519
04.05.2021, 23:06
Цитата Сообщение от nmcf Посмотреть сообщение
А для чего вообще делать noexcept для класса исключения?
Что бы гарантировать, что из эксепшена не вылетит другой эксепшен.
Иначе невозможно будет гарантировать надёжность ловушки исключений:
C++
1
2
3
4
5
6
7
8
try
{
    work();
}
catch(const std::exception& e)
{
    std::cerr << e.what();
}
Что будет, если из метода what вылетит эксепшен?
Ловушка потерпит фиаско: приложение погибнет от std::terminate.
0
7804 / 6568 / 2988
Регистрация: 14.04.2014
Сообщений: 28,705
04.05.2021, 23:18
Цитата Сообщение от eva2326 Посмотреть сообщение
Что будет, если из метода what вылетит эксепшен?
Там вроде бы речь шла о том, что объект throw генерирует исключение.

Я о том, что нет требования делать строго noexcept. Ну если там всё так плохо, что даже строка не создаётся, то толку от ловушки будет мало.
0
0 / 0 / 0
Регистрация: 22.11.2020
Сообщений: 42
06.05.2021, 10:05  [ТС]
eva2326
2 вопроса (ответь пож):

1) То есть если я правильно понял, то чтобы исключить возможность выброса исключения связанного с bad_alloc нам нельзя взаимодействовать с кучей и поэтому мы отказываемся от передаче по ссылке (правильно ?).

2) А что если я напишу так:
C++
1
explicit Error(const wstring mess) noexcept: message(std::move(mess)) {}
то есть параметр не wstring mess, а const wstring mess, мы же mess не меняем
0
0 / 0 / 0
Регистрация: 22.11.2020
Сообщений: 42
13.06.2021, 03:39  [ТС]
Короче это лучшее на что я пока способен:

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <codecvt>
 
using namespace std;
 
class Error : public exception {
    wstring message;
public:
 
    explicit Error(const wstring mess) noexcept: message{move(mess)} {}
 
    explicit Error(const string mess) noexcept {
        wstringstream wss{};
        wss << mess.c_str();
        message = wss.str();
    }
 
    template<typename elemType>
    Error &add(const elemType &mess) noexcept {
        wstringstream wss{};
        wss << L" " << mess;
        message += wss.str();
        return *this;
    }
 
    Error &add(const wstring_view &mess) noexcept {
        wstringstream wss{};
        wss << L" " << wstring{mess}.c_str();
        message += wss.str();
        return *this;
    }
 
    Error &add(const string &mess) noexcept {
        wstringstream wss{};
        wss << L" " << mess.c_str();
        message += wss.str();
        return *this;
    }
 
    Error &add(const string_view &mess) noexcept {
        wstringstream wss{};
        wss << L" " << string{mess}.c_str();
        message += wss.str();
        return *this;
    }
 
    const char *what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT {
        wcerr << L"Произошло исключение: " << endl;
        wcerr << message << endl;
        return "";
    }
 
};
 
 
/** -*- -*- -*- Клиентский код -*- -*- -*- */
 
int main() {
    setlocale(LC_ALL, "Russian");
    try {
        throw Error{L"Тест Error"}
                .add("!")
                .add(L"add const wchar_t *")
                .add("!!"s)
                .add("!!!"sv)
                .add(L"add wstring"s)
                .add(L"add wstring_view"sv)
                .add(1);
    } catch (const Error &error) {
        error.what();
    }
    system("pause");
    return 0;
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
13.06.2021, 03:39
Помогаю со студенческими работами здесь

Исключения ошибки
Здравствуйте программисты! int z; z = Convert.ToInt32(Console.ReadLine()); Подкажите пожалуйста,как мне словить ошибку если...

Уничтожить объект при возникновении в конструкторе обрабатываемого исключения
Наверняка ведь случается, что в конструкторе возникает исключение (неправильные данные и т.д.), а как в таком случае прописать в...

Исключения(ошибки) в Python
Прочитал про ошибки(исключения) в питоне, так вот возник вопрос об . Не могу понять что это за ошибка(пример ее если можно) *...

Как словить все исключения и ошибки?
ну то есть чтобы при исполнении было ясно в чем она

Найти и исправить ошибки в коде (исключения)
Есть такой код. По идее, при вводе, например, 5 и -5 должно выполняться throw bad_hmean(a, b); Но почему-то при любом вводе, в котором...


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

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
Оптимизация кода на разграничение прав доступа к элементам формы
Maks 13.04.2026
Алгоритм из решения ниже реализован на нетиповом документе, разработанного в конфигурации КА2. Задачи, как таковой, поставлено не было, проделанное ниже исключительно моя инициатива. Было так:. . .
Контроль заполнения и очистка дат в зависимости от значения перечислений
Maks 12.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: реализовать контроль корректности заполнения дат назначения. . .
Архитектура слоя интернета для сервера-слоя.
Hrethgir 11.04.2026
В продолжение https:/ / www. cyberforum. ru/ blogs/ 223907/ 10860. html Знаешь что я подумал? Раз мы все источники пишем в голове ветки, то ничего не мешает добавить в голову такой источник, который сам. . .
Подстановка значения реквизита справочника в табличную часть документа
Maks 10.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: при выборе сотрудника (справочник Сотрудники) в ТЧ документа. . .
Очистка реквизитов документа при копировании
Maks 09.04.2026
Алгоритм из решения ниже применим как для типовых, так и для нетиповых документов на самых различных конфигурациях. Задача: при копировании документа очищать определенные реквизиты и табличную. . .
модель ЗдравоСохранения 8. Подготовка к разному выполнению заданий
anaschu 08.04.2026
https:/ / github. com/ shumilovas/ med2. git main ветка * содержимое блока дэлэй из старой модели теперь внутри зайца новой модели 8ATzM_2aurI
Блокировка документа от изменений, если он открыт у другого пользователя
Maks 08.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа, разработанного в конфигурации КА2. Задача: запретить редактирование документа, если он открыт у другого пользователя. / / . . .
Система безопасности+живучести для сервера-слоя интернета (сети). Двойная привязка.
Hrethgir 08.04.2026
Далее были размышления о системе безопасности. Сообщения с наклонным текстом - мои. А как нам будет можно проверить, что ссылка наша, а не подделана хулиганами, которая выбросит на другую ветку и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru