Evgenii Legotckoi
Evgenii LegotckoiҚаз. 15, 2017, 5:31 Т.Қ.

C++ - Сабақ 011. Ерекшеліктер

Ерекшелік дегеніміз не? Бұл бағдарламаның стандартты тәртібімен қамтамасыз етілмеген жағдай. Мысалы, Вектор сыныбында жоқ элементке қол жеткізу әрекеті (біз оны сыныптар мақаласында талқылағанбыз). Яғни, вектор шектен тыс. Бұл жағдайда бағдарламаның орындалуын үзу үшін ерекше жағдайларды пайдалануға болады. Бұл қажет, өйткені

  • Әдетте, мұндай жағдайларда Вектор класының авторы пайдаланушы өз класын қалай пайдаланғысы келетінін білмейді, сонымен қатар бұл класс қандай бағдарламада қолданылатынын білмейді.
  • Вектор класының пайдаланушысы бұл класстың дұрыс жұмысын әрқашан бақылай алмайды, сондықтан оған бірдеңе дұрыс болмады деп хабарлау қажет.

C++ тілінде мұндай жағдайларды шешу үшін ерекшеліктер техникасын қолдануға болады.


Vector класында жоқ индекс бойынша элементке қол жеткізу әрекеті болған жағдайда ерекше жағдайды қалай жазу керектігін қарастырайық.

double& Vector::operator[](int i)
{
    if (i<0 || size()<=i) throw out_of_range{"Vector::operator[]"};
    return elem[i];
}

ауқымнан_ тыс ерекше жағдай осы жерде қолданылады. Бұл ерекшелік тақырып файлында анықталған .

throw операторы басқаруды Vector::operator функциясын тікелей немесе жанама түрде шақыратын кейбір функциядағы ауқымнан_ тыс түріндегі ерекше жағдай өңдеушісіне береді. Ерекшеліктерді өңдеу үшін мәлімдемелер блогын пайдалану керек catch көріңіз.

void f(Vector& v)
{
    // ...
    try { // блок обработки функции с исключением
        v[v.size()] = 7; // попытка доступа к элементу за пределами вектора
    }
    catch (out_of_range) { // ловим ошибку out_of_range 
        // ... обработки ошибки out_of_range ...
    }
    // ...
}

Инварианты

Сондай-ақ, try catch блоктары C++ ерекшелік механизмінің жұмысына инварианттылықты енгізетін бірнеше түрлі ерекшеліктерді өңдеуге мүмкіндік береді.

Мысалы, вектор класы жасалған кезде вектордың қате өлшемін алуы немесе құрамында болатын элементтер үшін бос жад таба алмауы мүмкін.

Vector::Vector(int s)
{
    if (s < 0) throw length_error{};
    elem = new double[s];
    sz = s;
}

Бұл конструктор екі жағдайда ерекшелік жасай алады:

  • өлшем аргументі ретінде теріс мән берілсе
  • new операторы жадты бөле алмаса

length_error стандартты ерекшелік операторы болып табылады, өйткені std кітапханасы өз жұмысында осы ерекшеліктерді жиі пайдаланады.

Ерекше жағдайды өңдеу келесідей болады:

void test()
{
    try {
        Vector v(−27);
    }
    catch (std::length_error) {
        // обработка отрицательного размера вектора
    }
    catch (std::bad_alloc) {
        // обработка ошибки выделения памяти
    }
}

Сіз сондай-ақ өзіңіздің ерекше жағдайларыңызды бөлектей аласыз.

Ерекшеліктер түрлері

Барлық стандартты кітапхана ерекшеліктер std::exception. мұрағатынан алынады.

Қазіргі уақытта ерекше жағдайлардың келесі түрлері бар:

  • логикалық_қате
  • жарамсыз_аргумент
  • домен_қатесі
  • ұзындық_қателігі
  • диапазоннан_ тыс
  • болашақ_қате (C++11)
  • орындау уақыты_қателігі
  • ауқым_қателігі
  • толып кету_қателігі
  • астыңғы_қате
  • жүйелік_қате (C++11)
  • ios_base::сәтсіздік (C++11-ден бастап)
  • нашар_түрі
  • нашар_cast
  • bad_weak_ptr (C++11)
  • нашар_функция_шақыруы (C++11)
  • нашар_бөлу
  • bad_array_new_length (C++11)
  • нашар_ерекшелік
  • ios_base :: сәтсіздік (C++ 11 дейін)

std::logic_error

Тақырып файлында анықталған ерекше жағдай

Ерекшелік ретінде лақтырылатын нысан түрін көрсетеді. Ол логикалық алғышарттың немесе алдын алуға болатын инварианттар класының бұзылуы сияқты бағдарламадағы дұрыс емес логиканың нәтижесі болып табылатын қателер туралы хабарлайды.

Бұл сынып тек орындау уақытында анықталатын қателер үшін негіз ретінде пайдаланылады.

std::жарамсыз_аргумент

Тақырып файлында анықталған ерекше жағдай

std::logic_error ішінен мұраланған. Жарамсыз аргумент болған жағдайда шығарылатын ерекше жағдайды анықтайды.

Мысалы, MSDN стандартты кітапханадан биттер класының объектісі болған кезде мысал береді

// invalid_arg.cpp  
// compile with: /EHsc /GR  
#include <bitset>  
#include <iostream>  

using namespace std;  

int main( )  
{  
   try   
   {  
      bitset< 32 > bitset( string( "11001010101100001b100101010110000") );  
   }  
   catch ( exception &e )   
   {  
      cerr << "Caught " << e.what( ) << endl;  
      cerr << "Type " << typeid( e ).name( ) << endl;  
   };  
}  
\* Output:   
Caught invalid bitset<N> char  
Type class std::invalid_argument  
*\ 

Бұл мысалда жарамсыз жол жіберілді, оның ішінде қате болатын «b» таңбасы бар.

std::domain_error

Тақырып файлында анықталған ерекше жағдай

std::logic_error ішінен мұраланған. Берілген аргумент үшін математикалық функция анықталмаған жағдайда шығарылатын ерекше жағдайды көрсетеді, мысалы:

std::sqrt(-1)

std::length_қате

Тақырып файлында анықталған ерекше жағдай

std::logic_error ішінен мұраланған. Нысан үшін шектен тыс әрекетті орындау әрекеті жасалған кезде шығарылуы керек ерекше жағдайды көрсетеді. Мақаланың басындағы вектордың өлшемі үшін көрсетілгендей.

std::ауқымнан_ тыс

Тақырып файлында анықталған ерекше жағдай

std::logic_error ішінен мұраланған. Нысанның мәндер ауқымы шектен шыққан кезде шығарылатын ерекше жағдайды көрсетеді. Мақаланың басында вектор мәндерінің диапазоны үшін көрсетілгендей.

std::future_error

Тақырып файлында анықталған ерекше жағдай

std::logic_error ішінен мұраланған. Асинхронды режимде жұмыс істейтін және ағындар кітапханасына тәуелді функция орындалмаса, бұл ерекшелік жойылуы мүмкін. Бұл ерекшелік std::error_code параметрімен үйлесімді қате кодын қамтиды.

std::runtime_error

Тақырып файлында анықталған ерекше жағдай

Оңай болжау мүмкін емес және орындалу уақытында шығарылуы керек ерекше жағдайлардың негізгі ерекшелігі болып табылады.

std::range_error

Тақырып файлында анықталған ерекше жағдай

Ерекшелік өзгермелі нүкте мәндерін есептеудегі қателер үшін пайдаланылады, компьютер мәнді өңдей алмаса, себебі ол тым үлкен немесе тым кішкентай. Егер мән интегралдық мән болса, underflow_error немесе overflow_error ерекше жағдайларды пайдалану керек.

std::overflow_error

Тақырып файлында анықталған ерекше жағдай

Ерекшелік интегралдық түрдегі өзгермелі нүкте мәндерін есептеудегі қателер үшін пайдаланылады, санның тым үлкен оң мәні, оң шексіздігі бар, дәлдік жоғалады, яғни. нәтиже соншалықты үлкен, оны IEEE754 нөмірі ретінде көрсету мүмкін емес.

std::underflow_error

Тақырып файлында анықталған ерекше жағдай

Ерекшелік интегралдық түрдегі өзгермелі нүкте мәндерін есептеудегі қателер үшін қолданылады, онда дәлдік жоғалады, яғни. нәтиже соншалықты кішкентай, оны IEEE754 нөмірі ретінде көрсету мүмкін емес.

std::system_error

Тақырып файлында анықталған ерекше жағдай

std::system_error – әртүрлі стандартты кітапхана функциялары (әдетте std::thread конструкторы сияқты операциялық жүйемен әрекеттесетін функциялар) шығаратын ерекшелік түрі. сәйкес * std::error_code * .

std::ios_base::сәтсіздік

Тақырып файлында анықталған ерекше жағдай

Енгізу/шығару функциялары сәтсіз болғанда шығарылатын ерекше жағдайларға жауапты.

std::bad_typeid

Тақырып файлында анықталған ерекше жағдай

Бұл түрдегі ерекшелік typeid операторы полиморфты түрдегі нөлдік көрсеткішке қолданылғанда шығарылады.

#include <iostream>
#include <typeinfo>

struct S { // Тип должен быть полиморфным
    virtual void f();
}; 

int main()
{
    S* p = nullptr;
    try {
        std::cout << typeid(*p).name() << '\n';
    } catch(const std::bad_typeid& e) {
        std::cout << e.what() << '\n';
    }
}

std::bad_cast

Тақырып файлында анықталған ерекше жағдай

Бұл ерекше жағдай нысанды мұрагерлік қатынасы жоқ нысан түріне шығару әрекеті жасалғанда орын алады.

#include <iostream>
#include <typeinfo>

struct Foo { virtual ~Foo() {} };
struct Bar { virtual ~Bar() {} };

int main()
{
    Bar b;
    try {
        Foo& f = dynamic_cast<Foo&>(b);
    } catch(const std::bad_cast& e)
    {
        std::cout << e.what() << '\n';
    }
}

std::bad_weak_ptr

Тақырып файлында анықталған ерекше жағдай

std::bad_weak_ptr std::weak_ptr сілтейтін кезде std::weak_ptr аргумент ретінде қабылдайтын std::shared_ptr конструкторлары ерекшелік ретінде шығарған нысан түрі. әлдеқашан жойылған нысан.

#include <memory>
#include <iostream>
int main()
{
    std::shared_ptr<int> p1(new int(42));
    std::weak_ptr<int> wp(p1);
    p1.reset();
    try {
        std::shared_ptr<int> p2(wp);
    } catch(const std::bad_weak_ptr& e) {
        std::cout << e.what() << '\n';
    }
}

std::жаман_функция_шақыруы

Тақырып файлында анықталған ерекше жағдай

Бұл ерекшелік std::function нысанының std::function::operator() әдісі шақырылып, функция нысанын алмаса, яғни ол nullptr ретінде жіберілген болса шығарылады. мысалы, инициализатор және функция нысаны ешқашан жіберілмеді.

#include <iostream>
#include <functional>

int main()
{
    std::function<int()> f = nullptr;
    try {
        f();
    } catch(const std::bad_function_call& e) {
        std::cout << e.what() << '\n';
    }
}

std::bad_alloc

Тақырып файлында анықталған ерекше жағдай

Жадты бөлу мүмкін болмаған кезде шақырылады.

std::жаман_массив_жаңа_ұзындық

Тақырып файлында анықталған ерекше жағдай

Ерекшелік келесі жағдайларда шығарылады:

  1. Жиым теріс өлшемге ие
  2. Жаңа массивтің жалпы өлшемі іске асыру арқылы анықталған ең үлкен мәннен асты
  3. Баптандыру элементтерінің саны баптандыру элементтерінің ұсынылған санынан асып түседі
#include <iostream>
#include <new>
#include <climits>

int main()
{
    int negative = -1;
    int small = 1;
    int large = INT_MAX;
    try {
        new int[negative];           // negative size
        new int[small]{1,2,3};       // too many initializers
        new int[large][1000000];     // too large
    } catch(const std::bad_array_new_length &e) {
        std::cout << e.what() << '\n';
    }
}

std::bad_ерекшелік

Тақырып файлында анықталған ерекше жағдай

std::bad_exception - келесі жағдайларда шығарылатын C++ ерекшелік түрі:

  1. Динамикалық ерекшелік спецификациясы бұзылса
  2. Егер std::exception_ptr ұсталған ерекше жағдайдың көшірмесін ұстаса және ерекше жағдай нысанының көшіру конструкторы current_exception ұстаған болса, онда ұсталған ерекше жағдай тасталады.
#include <iostream>
#include <exception>
#include <stdexcept>

void my_unexp() { throw; }

void test() throw(std::bad_exception)
{
    throw std::runtime_error("test");
}

int main()
{
    std::set_unexpected(my_unexp);
    try {
         test();
    } catch(const std::bad_exception& e)
    {
        std::cerr << "Caught " << e.what() << '\n';
    }
}
Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

P
  • Қаз. 15, 2017, 11 Т.Қ.

std::underflow_error - это не "число имеет слишком большое отрицательное значение", а потеря точности при вычислениях, т.е. результат настолько мал, что не может быть представлен числом в формате IEEE754

Evgenii Legotckoi
  • Қаз. 16, 2017, 2:46 Т.Ж.

Спасибо. Дополнил.

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз
Г

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:66ұпай,
  • Бағалау ұпайлары-1
t

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:33ұпай,
  • Бағалау ұпайлары-10
t

Qt - Тест 001. Сигналы и слоты

  • Нәтиже:52ұпай,
  • Бағалау ұпайлары-4
Соңғы пікірлер
G
GoattRockҚыр. 3, 2024, 1:50 Т.Қ.
Linux жүйесінде файлдарды қалай көшіруге болады Задумывались когда-нибудь о том, как мы привыкли доверять свои вещи службам грузоперевозок? Сейчас такие услуги стали неотъемлемой частью нашей жизни, особенно когда речь идет о переездах между …
d
dblas5Шілде 5, 2024, 11:02 Т.Ж.
QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssrАқп. 8, 2024, 6:43 Т.Қ.
Qt Linux - Сабақ 001. Linux астында Autorun Qt қолданбасы как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий КононенкоАқп. 5, 2024, 1:50 Т.Ж.
Qt WinAPI - Сабақ 007. Qt ішінде ICMP Ping арқылы жұмыс істеу Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
Енді форумда талқылаңыз
Evgenii Legotckoi
Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
F
FynjyШілде 22, 2024, 4:15 Т.Ж.
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …
BlinCT
BlinCTМаусым 25, 2024, 1 Т.Ж.
Нарисовать кривую в qml Всем привет. Имеется Лист листов с тосками, точки получаны интерполяцией Лагранжа. Вопрос, как этими точками нарисовать кривую? ChartView отпадает сразу, в qt6.7 появился новый элемент…
BlinCT
BlinCTМамыр 5, 2024, 5:46 Т.Ж.
Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
Evgenii Legotckoi
Evgenii LegotckoiМамыр 2, 2024, 2:07 Т.Қ.
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.

Бізді әлеуметтік желілерде бақылаңыз