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 Т.Ж.

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

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз
OI
  • Ora Iro
  • Жел. 24, 2024, 6:38 Т.Ж.

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

  • Нәтиже:40ұпай,
  • Бағалау ұпайлары-8
AD

C++ - Тест 004. Указатели, Массивы и Циклы

  • Нәтиже:50ұпай,
  • Бағалау ұпайлары-4
m
  • molni99
  • Қаз. 26, 2024, 1:37 Т.Ж.

C++ - Тест 004. Указатели, Массивы и Циклы

  • Нәтиже:80ұпай,
  • Бағалау ұпайлары4
Соңғы пікірлер
ИМ
Игорь МаксимовҚар. 22, 2024, 11:51 Т.Ж.
Django - Оқулық 017. Теңшелген Django кіру беті Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii LegotckoiҚаз. 31, 2024, 2:37 Т.Қ.
Django - Сабақ 064. Python Markdown кеңейтімін қалай жазуға болады Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZEҚаз. 19, 2024, 8:19 Т.Ж.
Qt Creator көмегімен fb3 файл оқу құралы Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь МаксимовҚаз. 5, 2024, 7:51 Т.Ж.
Django - Сабақ 064. Python Markdown кеңейтімін қалай жазуға болады Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas5Шілде 5, 2024, 11:02 Т.Ж.
QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Енді форумда талқылаңыз
Evgenii Legotckoi
Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
t
tonypeachey1Қар. 15, 2024, 6:04 Т.Ж.
google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
NSProject
NSProjectМаусым 4, 2022, 3:49 Т.Ж.
Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
9
9AnonimҚаз. 25, 2024, 9:10 Т.Ж.
Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

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