Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.83/41: Рейтинг темы: голосов - 41, средняя оценка - 4.83
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712

Наследование от std::exception

06.11.2019, 14:11. Показов 8941. Ответов 29
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Приветствую всех. Создаю библиотеку классов и в некоторых (исключительных) случаях планирую кидать исключения. Скажите, имеет ли смысл класс исключения наследовать от std::exception? Если имеет, то укажите, пожалуйста, причины.
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
06.11.2019, 14:11
Ответы с готовыми решениями:

Обработка исключений типа std::exception
Пытаюсь выполнить участок кода: try { socket_=new Network::ClientSocket(Host,Port); } catch (std::exception *e) { ...

Unhandled exception at 0x7c812a5b : Microsoft C++ exception: std::bad_alloc at memory location 0x0012f350
что то я запутался совсем. подскажите где глюк? Считываю из XML данные: char* ValueVariable(длинная символьная строка) пытаюсь ее...

Создание своего класса исключений, наследование std::exception
хотел создать свой класс исключений пронаследовав от std::exception, но немного запутался в конструкторах... конструктор же не наследуется,...

29
10.11.2019, 18:14
Студворк — интернет-сервис помощи студентам

Не по теме:

Цитата Сообщение от hoggy Посмотреть сообщение
второй признак делитанта:
третий: он в слове дилетант делает 2 ошибки
Кликните здесь для просмотра всего текста
шутка :D

0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
10.11.2019, 20:44  [ТС]
Цитата Сообщение от Azazel-San Посмотреть сообщение
поэтому для предотвращения своих ошибок я бы воспользовался ЮТ
Что такое ЮТ?

Цитата Сообщение от DrOffset Посмотреть сообщение
Потому что так захотел разработчик библиотеки.
Цитата Сообщение от Azazel-San Посмотреть сообщение
Значит разработчики стандартной библиотеки решили иначе
То есть, разработчики стандартной библиотеки решили, что выход за пределы массива - это исключительная ситуацию, и все сказали ладно, хорошо. Я, как разработчик своей библиотеки, решаю, что обращение к несуществующему символу в классе строки моей библиотеки - это исключительная ситуация, и в меня кидают тухлыми помидорами. Что за дискриминация? Почему здесь никто не сказал, что разработчики стандартной библиотеки "сделали немного не правильно", или "кидать исключение в этом случае - это неправильно, ибо это не исключение, а ошибка программиста"?

Цитата Сообщение от Azazel-San Посмотреть сообщение
Представьте лица тех разработчиком приложение которых начало падать из-за того что ваша библиотека где-то не обрабатывает исключения..
Моя библиотека где надо будет обрабатывать исключения. Здесь же случай, когда моя библиотека кидает исключение. Она не должна его обрабатывать.
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
10.11.2019, 23:52
Цитата Сообщение от d7d1cd Посмотреть сообщение
Почему здесь никто не сказал, что разработчики стандартной библиотеки "сделали немного не правильно", или "кидать исключение в этом случае - это неправильно, ибо это не исключение, а ошибка программиста"?
В "этом случае" - это в каком?
Вы не читали мое сообщение?
Цитата Сообщение от DrOffset Посмотреть сообщение
нет особого смысла выяснять эти вещи в отрыве от проекта
Именно применительно к проекту выясняется "этот случай".

Цитата Сообщение от d7d1cd Посмотреть сообщение
То есть, разработчики стандартной библиотеки решили, что выход за пределы массива - это исключительная ситуацию, и все сказали ладно, хорошо.
По моему опыту (не самому маленькому из участников на этом форуме), метод вектора at(), кидающийся исключением, используется во много-много раз реже, чем operator[], который их не кидает. В чем же тут выражается "ладно, хорошо"? По-моему множество программистов, чей код я видел, и я сам, уже давно проголосовали действием. Просто прочитайте еще раз мое прошлое сообщение.

В момент проектирования стандартной библиотеки в будущее заглянуть было проблематично, а из С++ фичи выпиливаются с достаточно большой неохотой. И если у нас нет железобетонной причины удалить что-то, это никто делать не будет. А в случае с методом at() одного лишь "редко кому надо, т.к. обычно диапазон индексов проверяет вышестоящая функция" недостаточно, чтобы удалить метод at из библиотеки.

Цитата Сообщение от d7d1cd Посмотреть сообщение
Я, как разработчик своей библиотеки, решаю, что обращение к несуществующему символу в классе строки моей библиотеки - это исключительная ситуация, и в меня кидают тухлыми помидорами. Что за дискриминация?
Ну так вы собирались сделать operator[] бросающим исключение. А разработчики стандартной библиотеки этого не делали - их operator[] ничего не кидает, в отладочной версии там срабатывает assert, как уже было сказано. А то, что в составе библиотеки есть другой метод, который исключение бросает - ничего не значит в отрыве от задачи. Безотносительно того, что, как я уже сказал, он не особо пользуется популярностью. В стандартной библиотеке есть стандартное оправдание для таких решений - оправдание простое - она стандартная, и поэтому старается давать инструменты для широкого круга задач, а ваша библиотека специализирована предметной областью, в рамках которой вы пишете код. Дополнительно, у вас нет ограничений стандартной библиотеки, и вы при разработке можете учесть накопленный опыт и не делать глупостей, особенно с учетом того, что сфера применения вашей библиотеки априори уже, чем стандартной. Ну и, наконец, если бы вы действительно осознанно решили, что ваше решение с исключением правильное, то наверное смогли бы это дело обосновать? Если вы не можете обосновать свое тех. решение, значит решение не было проработано, а в инженерной деятельности - это ведет к большим проблемам, знаете ли

И лично я в своих проектах никогда не использую метод at у вектора, именно по той причине, что я не знаю таких задач, на которых он лучше бы справился, чем оператор[], а значит я не могу обосновать, что мне нужен метод at, а раз я не могу это обосновать, значит он мне не нужен. Логика тут простая. При этом мне хватает ума предположить, что то, что я не знаю таких задач, не означает, что их нет в природе. Поэтому я не буду кричать, что разработчики std идиоты, потому что сделали бесполезный метод.
Теперь вам для себя надо решить, нужен ли вам метод индексации проверяющий диапазон на каждом обращении и бросающий исключение, или нет, а не пытаться запомнить правила "туда ходи" и "сюда не ходи". Я вам не правила выше озвучивал, а к здравому смыслу вашему обращался, к анализу вашей предметной области и потребностей вашего проекта.
1
Mental handicap
 Аватар для Azazel-San
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
11.11.2019, 00:23
Цитата Сообщение от d7d1cd Посмотреть сообщение
Что такое ЮТ?
Юнит Тесты.
Цитата Сообщение от d7d1cd Посмотреть сообщение
Здесь же случай, когда моя библиотека кидает исключение.
Опять-таки, как уже было сказано Вы как разработчик своей библиотеки не можете принимать бездумные решения. Как минимум прежде чем так делать стоит все проанализировать, а захотят ли пользователи вашей библиотеки ловить исключения? Ожидают ли они это? Надо ли им это и вам?
Зачастую попросту отказываются от одной библиотеки в пользу другой только потому что та другая не кидает исключений или наоборот.
Цитата Сообщение от DrOffset Посмотреть сообщение
В момент проектирования стандартной библиотеки
То таки метод at() был задуман еще с самого начала когда ее писал Степанов и тот другой?
Меня почему-то не покидает ощущение, что где-то оглядывались на Джаву.
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
11.11.2019, 00:29
Цитата Сообщение от Azazel-San Посмотреть сообщение
То таки метод at() был задуман еще с самого начала когда ее писал Степанов и тот другой?
Тот, другой - это Ли
И ответ - нет. Метода at в достандартной реализации от HP не было.
1
Mental handicap
 Аватар для Azazel-San
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
11.11.2019, 01:00
Цитата Сообщение от DrOffset Посмотреть сообщение
Метода at в достандартной реализации от HP не было.
А когда его добавили? Он был добавлен просто со временем? Или когда уже заехали в стандарт и был отдельный пропозал?
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
11.11.2019, 09:35
Цитата Сообщение от Azazel-San Посмотреть сообщение
А когда его добавили?
Насколько мне известно, в промежутке между осенью 1994 и весной 1995.
Если удастся найти текст документа WG21/N0527, то можно будет ответить точнее.
1
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
11.11.2019, 15:20
Лучший ответ Сообщение было отмечено DrOffset как решение

Решение

Цитата Сообщение от d7d1cd Посмотреть сообщение
Расскажите.
И никто из 3-х человек не сказал что делать, если возникает ситуация в приведенном выше примере.
во-первых, нужно понимать, какие бывают классы ошибок,
и как с ними нужно работать.


есть 3 класса ошибок:

1. ошибка пользовательского ввода.

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

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



2. исключительная ситуация.

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

например, нужно записать данные на диск.
код программы то написан правильно,
но где гарантии что на диске есть место?

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

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

по этой причине, если функция может спровоцировать исключительную ситуацию,
результат её работы в обязательном порядке нужно проверить.

что не так с этим кодом?
C++
1
2
3
4
5
6
db::connection connect(login, password);
 
// --- проверим, смогли ли мы подключиться к БД
if(connect)
    // --- подключение успешное
    connect.query(request);  // <--- выполняем запрос
этот фрагмент кода содержит баг.
что, если сразу же после успешного подключения,
произошел дисконнект, и теперь физически с базой нет связи?
в этом случае метод connect.query(request); потерпит неудачу.
однако алгоритм продолжит работу так, словно всё хорошо.
может быть крашнется где нибудь дальше по тексту.
и хорошо, если данные при этом не попортит.

правильный код:

C++
1
2
3
4
5
6
7
8
9
10
db::connection connect(login, password);
 
// --- проверим, смогли ли мы подключиться к БД
if(connect)
    // --- всегда проверяем результат работы 
    if(!connect.query(request)) 
    {
        std::cout << "error: " << connect.what() << '\n';
        return false;
    }
механизм эксепшенов удобен тем,
что не нужно на каждый чих писать очередной if
но главная его киллер-фича в том,
что в случае неудачи гарантируется,
что алгоритм не будет продолжать выполнение с некорректными данными.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
try
{
    db::connection connect(login, password);
    connect.query(request);
 
    // --- гарантируется, что если что-то пошло не так, 
    // --- функция не будет запущена
    work(); 
}
catch(const std::exception& e)
{
    std::cout << "error: " << connect.what() << '\n';
    return false;
}
уже не получится ничайно забыть проверить код возврата,
или что-то в таком духе.

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

это - обширная тема.
тянет на отдельную книгу тему
сейчас я не буду в неё углубляться.


3. программная ошибка.

неправильно написанный код.
программист напортачил.

например, распространенная ошибка новичка:

C++
1
2
for(size_t i = 0; i <= size; ++i)
    arr[i]->work();
некорректный фрагмент i <= size приводит к выходу за пределы диапазона.
в лучшем случае будет краш.
в худшем - отработает на неконсистентных данных.

что можно сделать с такой ошибкой?

исключение бросать бесполнезно.
исключение предотварит UB,
но сам алгоритм от этого рабочим не станет.

то есть, программа как не работала,
так и будет дальше не работать.

на самом деле единственный способ решения проблемы - позвать программиста,
и пускай исправляет баг.

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

для этого применяют техники привентивной защиты от ошибок:

1. assert
идея настолько же проста, насколько гениальная:
есть две конфигурации сборки: дебаг (отладочная) и релиз (окончателньая версия)

в дебаге присутствуют и исполняются все ассерт-проверки.

а вот в релизную сборку ассер-проверки не входят.
(они вообще не участвуют в компиляции)

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

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

существует обратная зависимость количества багов от количества ассертов.
чем больше ассертов, тем меньше багов.
чем меньше ассертов, тем больше багов.

особо продвинутые люди приспособили ассерты для контрактного программирования.

пример:

C++
1
2
3
4
5
6
7
8
9
10
void calculate(const param& arg)
{
    // предусловие
    assert(arg > 0);
 
    // work! work! work!
 
    // постусловие
    assert(result >= 0.0 && result <= 1.0);
}
помимо дотошного контроля,
который сразу уменьшит количество багов этак на 95%
ассерты делают код более читабельным.
сразу видны ограничения, и каким ожидается результат.

2. авто-тесты

например, организация поставила перед тобой очень важную и отвественную задачу:

нужно сделать функцию,
которая принимает два целых числа и возвращает их сумму:
C++
1
int summ(const int a, const int b) noexcept;
вот как ты гарантируешь качество своей работы?
как минимум, нужно убедиться, что код вообще компилируется.
далее, убедиться, что функция работает как ожидается
для этого ты можешь сделать отдельный маленький проект,
где проиллюстрируешь использование функции:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
 
int summ(const int a, const int b) noexcept 
{
    return a + b;
}
 
int main()
{
    const int result = summ(2, 3);
 
    if(result == 5)
        std::cout << "SUCCESS\n";
    else
        std::cout << "FAILED\n";
}
ты знаешь, что сумма 2 и 3 даст 5.
а значит можешь написать код,
который проверит правильно ли работает твоя функция.

такой отдельный мини-проектик,
который контролирует корректность работы функционала,
называется "юнит-тестом"

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

после успешного прохождения всех тестов,
уже можно смело собирать релизную сборку.

3. пожалуй самая мощная техника.
смысл техники в том, что бы изначально проектировать свои функции таким образом,
что бы их нельзя было использовать неправильно.

пример плохого кода (уровень: новичок):

C++
1
2
3
4
void view(const game_object* obj)
{
    obj->about_me();
}
объявление функции определяет возможности и ограничения её использования.
это - контракт между функцией и программистом.
в данном случае функция говорит: "я прошу указатель в качестве аргумента"
а значит программист может подсунуть любой указатель типа const game_object*
а значит, казалось бы, он имеет полное право подсунуть nullptr,
что скорее всего приведет к аварии (access violation)

пример плохого кода (уровень: балбес):

C++
1
2
3
4
5
void view(const game_object* obj)
{
    assert(obj);
    obj->about_me();
}
здесь мы видим уже более грамотный подход.
балбес указал в документации,
что нужно передавать указатель на реальный объект.
нулевые указатели запрещены.
запрет на нулевые указатели конктролирует ассерт.
а значит, если даже ничайно передать nullptr,
то отладочная сборка сразу же покажет проблему.

вроде бы все хорошо.
на самом деле не всё хорошо.

почему я назвал код плохим, а его автора балбесом?
потому что этот болван на ровном месте сам себе создал проблему,
а потом начал героически её преодолевать.

вот так должен выглядеть нормальный код:
C++
1
2
3
4
void view(const game_object& obj)
{
    obj.about_me();
}
ожидаешь реальный объект?
используй специально предназначенные для этого ссылки.
уже не получится передать nullptr
и не нужно дополнительно ничего проверять.


или такой пример:
пользователя просят ввести цифры, а он вводит буквы.
приходится дополнительно проверять корректность введеных им данных.

но что, если просто физически запретить вводить с клавиатуры что либо, кроме цифр?
в этом случае ошибка ввода в принципе не сможет возникнуть:

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
80
81
82
83
84
85
86
87
#include <iostream>
#include <conio.h>
#include <cassert>
#include <sstream>
#include <string>
 
struct input
{
    template<class Checker>
    input(const char* msg, const Checker& checker)
        : m_data()
    {
        assert(msg);
        assert(::std::cout);
        assert(this->m_data.empty());
        ::std::cout << msg; 
        assert(::std::cout);
 
        for (;;)
        {
            auto code = ::_getch();
 
            // --- enter
            if (code == 13 || code == 27)
            {
                ::std::cout << '\n';
                break;
            }
                
            // backspace
            if(code == 8)
            {
                ::std::cout << "\b \b";
                if(!this->m_data.empty())
                    this->m_data.pop_back();
            }
            else
            {
                const auto symbol = static_cast<char>(code);
                if(!checker(this->m_data, symbol))
                    continue;
                this->m_data += symbol;
 
                assert(!this->m_data.empty());
                assert(::std::cout);
                ::std::cout << "*";
                assert(::std::cout);
            }
        }
    }
 
    template<class Result>
    operator Result() 
    {
        Result result;
        ::std::stringstream ss(this->m_data);
        assert(ss);
        ss >> result;
        assert(ss);
        return result;
    }
private:
    ::std::string m_data;
};
 
int main()
{
    // --- вводить можно только цифры
    // --- и не более 6ти символов длиной
 
    // --- вместо пароля в консоли должны отображатсья звёздочки
 
    const auto checker 
        = [](const ::std::string& stored, const char symbol) 
    {
        if(stored.length() == 6)
            return false;
        return symbol >= '0' && symbol <= '9';
    };
 
    ::std::string result = ::input(
        "\nenter password (only 6 numbers): ",
        checker
    );
 
    ::std::cout << "(system) read password: '" << result << "'\n";
}
сделай так, что бы твоим инструментом нельзя было пользоваться не правильно,
и ты привентивно уберешь себя и своих юзеров от ошибок.




а во-первых, когда пишешь код, всегда задай себе следующие вопросы:


1.
что здесь может пойти не так?
например, индекс за пределами диапазона.

2.
как можно идентифицировать наличие проблемы?
например, проверить индекс на максимально допустимый.

3.
самое главное(!)
что делать теперь с этой проблемой?

вот ты предлагаешь использовать эксепшены.


ок, допустим, оператор[] бросил эксепшен.
Вася в своём коде благополучно поймал это исключение.
что дальше?
как это поможет?
никак.

некорректный алгоритм работать не будет.
и никакими эксепшенами это не исправить.

кто-то сейчас обязательно вспомнит про метод std::vector::at
ну так вот, я не знаю кто и зачем его завёз в язык,
но на практике он бесполезен.

если приложение было недостаточно хорошо протестированно,
метод at() не спасет.
а если хорошо - то он попросту не нужен.

кто-то скажет: режим "паранойи".
параноики не любят ассерты за то, что те выпиливаются из релиза.
вместо ассертов они либо используют эксепшены во все поля,
либо используют идиому raise

raise в дебаге ведет себя как обычный assert,
а в реализе - кидается эксепшенами.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#pragma once
 
#ifdef NDEBUG
    //release
    #include <stdexcept>
#else
    //debug
    #include <cassert>
#endif
#define dTOOLS_RAISE_USED_ 
//================================================================================
#ifdef NDEBUG
    //release
    #define dRAISE(...) \
        throw ::std::runtime_error(__VA_ARGS__);
#else
    //debug
    #define dRAISE(...) \
        { assert(0  &&  __VA_ARGS__ ); }
#endif
//================================================================================
суть паранойи - проверки должны быть и в релизе тоже.
лучше пусть снижается быстродействие и растет расход памяти,
главное, что бы никакая ошибка не была ничайно пропущена.

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

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

твоя задача несложная, но очень ответственная:
нужно написать малюсенький простенький плагин (dll),
ничего особенного.
но если твой плагин крашнется,
он потянет за собой весь процесс.
и если торговый сервер упадет в самый разгар рабочего дня...


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

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

а иной балбес будет использовать at(), молиться и поститься.

4
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
20.11.2019, 18:38  [ТС]
hoggy, это было мощно!!! Спасибо за ликбез!!!
0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
20.11.2019, 19:44
Цитата Сообщение от hoggy Посмотреть сообщение
второй признак делитанта:
когда на кастомный эксепшен пытаются навесить блэкджек со шлюхами,
забывая об отказоусточивости последнего.
Как лучше построить механизм обработки ошибок на основе исключений?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
20.11.2019, 19:44
Помогаю со студенческими работами здесь

Unhandled exception at at 0x75E717D2 in ConsoleApplication24.exe: Microsoft C++ exception: std::out_of_range at memory l
Здравствуйте, помогите пожалуйста, при проходе через последний цикл выдаёт вот такую ошибку: Unhandled exception at at 0x75E717D2 in...

Выдаёт ошибку "Unhandled exception at 0x00007F exception: std::bad_alloc in memory location"
Добрый день, друзья не могли бы помочь разобраться, почему выдаёт такую ошибку? Вот #include &lt;iostream&gt; #include...

Вылетает на std::length_error exception
название не очень отражает суть вопроса, но лучше я предумать не смог. Есть программа собранная в дебаге (-g) к ней линкуется только одна...

Грамотно обработать ошибку std::exception
struct Node { Node(int data): data_(data) {} int data_; // полезная часть списка Node* next; // указатель на следующий...

Ошибка при работе с std::exception*
Почему в случаях 1 и 3 выводится нормальный e.what(), а во втором - ошибочный? Как это исправить? #include &lt;iostream&gt; #include...


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

Или воспользуйтесь поиском по форуму:
30
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru