Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.73/55: Рейтинг темы: голосов - 55, средняя оценка - 4.73
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602

Virtual и noreturn

23.02.2015, 19:57. Показов 11051. Ответов 55
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Возможно ли подружить virtual и noreturn? Пишу:
C++
1
2
3
4
5
struct test
{
    int func(){error();}
    [[noreturn]]virtual void error(){throw 0;}
};
Компилятор ругается что мол warning: no return statement in function returning non-void. То есть, атрибут noreturn он молча проигнорировал.
1
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
23.02.2015, 19:57
Ответы с готовыми решениями:

Атрибут [[noreturn]]
Атрибут ] у функций насколько я понимаю говорит компилятору что данная функция не должна возвращать управление (например, представим...

Protected abstract virtual base pure virtual private destructor
Хай, all) Вопрос не для начинающих и дурацкий) В разделе для экспертов публиковать не стал, чтобы не засорять его) Наткнулся тут на...

Какая разница между "void virtual" и "virtual void"?
какая разница между этими двумя записями viod virtual xexe() =0; и virtual void xexe()=0; Возможно это "нубо" вопрос но ...

55
19506 / 10109 / 2463
Регистрация: 30.01.2014
Сообщений: 17,833
25.02.2015, 10:49
Лучший ответ Сообщение было отмечено Renji как решение

Решение

Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Renji Посмотреть сообщение
По крайней мере, если объявить виртуальную функцию noexcept, тоже самое потребуют и от всех ее переопределений. А то что перегружать по noreturn нельзя, так и по типу возвращаемого значения нельзя. Но тип возвращаемого значения вроде как опять-же часть сигнатуры.
Давай по простому:
Атрибуты в сигнатуру водят? На данный момент ответ - нет. Нарушений каких-либо со стороны компилятора нет. Виртуальная функция в наследнике - это другая функция, [[noreturn]] на ее не распространяется, точно так же как это не распространяется, например, на gcc-шные __attribute__ ((<что-то>)). Вот и весь ответ.
А проверить тот факт, что компиляторы таки это дело отслеживают, можно просто: добавить final и убедиться, что warning пропал. Как только компилятор получил гарантии, что никто не будет более переопределять эту функцию, то сразу убрал warning.
Есть факт, ну и чего с ним спорить теперь? Если хочешь изменить положение вещей - можно оформить предложение в комитет, благо есть возможность.
0
 Аватар для Voivoid
710 / 283 / 16
Регистрация: 31.03.2013
Сообщений: 1,340
25.02.2015, 12:18
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
а зачем мне все грубят(притом я пытаюсь помочь а мне в глаза с*уt?)

Не по теме:

Ну наверное потому что это не помощь, а скорее медвежья услуга, от неё больше вреда чем пользы. Я конечно понимаю, что на любом языке можно писать как на фортране, но другим-то зачем это советовать?



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

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
void handle() {
  try {
    throw;
  }
  catch( const std::exception& ex ) {
    // do stuff
  }
}
 
void f() {
  try {
    // do stuff
  }
  catch( ... ) {
    handle();
  }
}
 
void g() {
  try {
    // do stuff
  }
  catch( ... ) {
    handle();
  }
}
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
25.02.2015, 13:45
Цитата Сообщение от Voivoid Посмотреть сообщение
вдруг кто не знает:
ИМХО: "хрень полная".

Детали:

Если вам известно, что эксепшен является наследником const std::exception,
то нет проблемы разрезолвить его в ловушке вида: catch( const std::exception& ex ),
что делает void handle() избыточным.

Ловушки вида catch( ... ) используется в случаях:

1.
Когда точный тип эксепшена не известен.
(а значит не существует предусмотренного обработчика на этот случай)
Для эвристического анализа ситуации, в отказоустойчивых системах.

2. Когда нужно отложить обработку всех исключений на более поздний срок:

http://rextester.com/IUVTX48212

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
//Title of this code
//g++  4.8.2
 
#include <stdexcept>
#include <iostream>
#include <vector>
 
using namespace std;
 
typedef std::vector<std::exception_ptr>
    Exeptions;
 
Exeptions gExeptions;
 
void Work()
{
    static size_t num = 0;
    try{
        ++num;
        throw  std::logic_error( "hello, cyberforum: " + std::to_string(num) );
    }
    catch(...)
    {
        //<--- сохраняем эксепшен, для того, что бы обработать его позже
        // никаких вспомогательных функций для этого не требуется
        gExeptions
            .emplace_back( std::current_exception() );
    }
}
 
void ViewExceptions()
{
    // обработка всех отложенных эксепшенов
    for (const auto& e : gExeptions)
    {
        try
        {
            if (e != nullptr)
                std::rethrow_exception(e);
        }
        catch (const std::exception& e)
        {
            std::cout << e.what() << '\n';
        }
        catch (...)
        {
            std::cout << "unkown\n";
        }
    }
}
 
 
int main()
{
    std::cout << "Hello, world!\n";
    
    for(size_t n=0;n<10;++n)
        Work();
    
    ViewExceptions();
}
0
19506 / 10109 / 2463
Регистрация: 30.01.2014
Сообщений: 17,833
25.02.2015, 14:16
Цитата Сообщение от hoggy Посмотреть сообщение
ИМХО: "хрень полная".
Скажем так, это не хрень, а несколько устаревшая техника в свете текущих возможностей языка.
Конкретно вот это:
Цитата Сообщение от hoggy Посмотреть сообщение
никаких вспомогательных функций для этого не требуется
В С++03 как раз таки требовало вспомогательных функций примерно с такими кишками. См. boost::exception (конкретно механизм эмуляции current_exception).
0
 Аватар для Voivoid
710 / 283 / 16
Регистрация: 31.03.2013
Сообщений: 1,340
25.02.2015, 14:27
Цитата Сообщение от hoggy Посмотреть сообщение
Если вам известно, что эксепшен является наследником const std::exception,
то нет проблемы разрезолвить его в ловушке вида: catch( const std::exception& ex ),
Э-э-э, лол, суть-то совсем не в этом, а в том, что подобная конструкция позволит использовать один обработчик
в различных местах без копипасты.

Цитата Сообщение от DrOffset Посмотреть сообщение
Скажем так, это не хрень, а несколько устаревшая техника в свете текущих возможностей языка.
Это каких?
0
19506 / 10109 / 2463
Регистрация: 30.01.2014
Сообщений: 17,833
25.02.2015, 15:05
Цитата Сообщение от Voivoid Посмотреть сообщение
Это каких?
Я отвечал в констексте примеров hoggy. Имелись в виду те инструменты, которые он продемонстировал в примере сохранения исключения. До С++11 эти вещи эмулировалсиь с помощью приведенных тобой конструкций (в boost::exception).

Цитата Сообщение от Voivoid Посмотреть сообщение
суть-то совсем не в этом, а в том, что подобная конструкция позволит использовать один обработчик
в различных местах без копипасты.
А не указывает ли присутствие в разных местах программы совершенно одинаковых обработчиков (особенно предполагая, что таких catch(что-то-там) может быть несколько) на ошибку проектирования?
И почему нельзя написать так?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void handle(const std::exception const & e) {
      // do stuff
}
 
void f() {
  try {
    // do stuff
  }
  catch(const std::exception const & e) {
    handle(e);
  }
}
 
void g() {
  try {
    // do stuff
  }
  catch(const std::exception const & e) {
    handle(e);
  }
}
Методика, которую ты показал, совершенно точно не "хрень", но, ИМХО, оправданное применение ее лежало немного в другой плоскости. Теперь в этой плоскости есть более правильные инструменты.
0
 Аватар для Voivoid
710 / 283 / 16
Регистрация: 31.03.2013
Сообщений: 1,340
25.02.2015, 15:18
Цитата Сообщение от DrOffset Посмотреть сообщение
И почему нельзя написать так?
А если надо ловить несколько типов исключений? В каждой функции писать портянки catch'ей?

Цитата Сообщение от DrOffset Посмотреть сообщение
А не указывает ли присутствие в разных местах программы совершенно одинаковых обработчиков (особенно предполагая, что таких catch(что-то-там) может быть несколько) на ошибку проектирования?
Ну-у-у, сходу сложно сказать. Мне данная конструкция за все время пригодилась раза два, да и то я сейчас уже не помню подробностей.
0
19506 / 10109 / 2463
Регистрация: 30.01.2014
Сообщений: 17,833
25.02.2015, 15:54
Цитата Сообщение от Voivoid Посмотреть сообщение
А если надо ловить несколько типов исключений? В каждой функции писать портянки catch'ей?
Давай так. Я не экстремист, не будут утверждать, что подобная техника не найдет применения в современных условиях.
Но лично я (лично я) стремился бы к обобщению на уровне иерархий исключений, а не на уровне обработчиков. И мое мнение, что необходимость присутствия совершенно одинаковых портянок из catch`ей (что ты предлагаешь вынести в функцию как решение) в разных частях программы тонко намекает на некую архитектурную проблему.
(На всякий случай, вот вопросы, которые помогут понять ход моих мыслей: 1) если действия разные, почему у них одинаковая портянка catch`ей? 2) если действия одинаковые, то почему они в разных частях программы?)
Повторюсь, я не экстремист, пропогандировать свое видение в массы не буду. Это лишь мнение.
2
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
26.02.2015, 03:27
Цитата Сообщение от Voivoid Посмотреть сообщение
Э-э-э, лол, суть-то совсем не в этом, а в том, что подобная конструкция позволит использовать один обработчик
в различных местах без копипасты.
сама по себе такая формулировка в контексте обработки исключений неприятно пахнет.

Цитата Сообщение от DrOffset Посмотреть сообщение
В С++03 как раз таки требовало вспомогательных функций примерно с такими кишками.
я бы понял, если бы чел продемонстрировал "отложенную обработку" исключений, используя технику с++03.
однако, он использует это совсем для другой цели: размазывает одинаковые обработки по всему коду проекта.
что не есть хорошо.
0
19506 / 10109 / 2463
Регистрация: 30.01.2014
Сообщений: 17,833
26.02.2015, 09:00
Цитата Сообщение от hoggy Посмотреть сообщение
он использует это совсем для другой цели: размазывает одинаковые обработки по всему коду проекта.
Ну по поводу этого я свое мнение выше высказал.
0
 Аватар для Voivoid
710 / 283 / 16
Регистрация: 31.03.2013
Сообщений: 1,340
26.02.2015, 16:12
Цитата Сообщение от DrOffset Посмотреть сообщение
Но лично я (лично я) стремился бы к обобщению на уровне иерархий исключений, а не на уровне обработчиков
Кто бы спорил. Вопрос в том, всегда ли это возможно. Вот скажем такой пример пришел в голову:

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
class model {
private:
  void update_from_database() {
    try {
      //some code that calls third-party DB lib
    }
    catch(...) {
      handle_db_exception_then_rethrow();
    }
  }
 
  void store_to_database() {
    try {
      //other code that calls third-party DB lib
    }
    catch(...) {
      handle_db_exception_then_rethrow();
    }
  }
 
  void handle_db_exception_then_throw() {
    try {
      throw;
    }
    catch(const DBException& ex ) {
      // write some low-level logs, do rollback or whatever is needed
      throw std::runtime_error( format_ex_message( ex ) );
    }
    catch(const std::exception& ex ) {
      // write some low-level logs, do rollback or whatever is needed
      throw;
    }
    catch(...) {
      // write some low-level logs, do rollback or whatever is needed
      throw;
    }
  }
};
Думаю по названиям в коде конекст более-менее понятен. Вынести в одну функци работу с базой дабы завернуть её в один try-catch вряд-ли возможно ( ну, зависит от библиотеки конечно ). Можно конечно сделать финт ушами с функцией которая принимает произвольный функтор с некием действием которое выполняется в try-catch, но это решением по мне так в высшей степени сомнительно

Есть какие-нибудь предложения?
0
19506 / 10109 / 2463
Регистрация: 30.01.2014
Сообщений: 17,833
26.02.2015, 17:10
Voivoid, насколько я вижу, ты предлагаешь учесть в этой задаче следующие ограничения:
1) Данный код - библиотека, которая не имеет права кидать исключения, либо не имеет права кидать исключения не являющиеся наследниками std::exception. Поэтому мы не можем вынести уровень обработки этих ситуаций выше методов update_from_database и store_to_database
2) Вытекает из первого. DBException - не наследник std::exception.
3) По каким-то не зависящим от нас причинам мы не можем заменить DBException на аналогичного наследника std::exception, либо полностью заменить библиотеку работы с DB на другую.
Если я все правильно обозначил выше, то соображения будут такие:
Я достаточно давно же работаю с legacy и не испытываю никаких иллюзий по поводу таких ситуаций. В том плане, что прекрасно понимаю откуда тут могут расти ноги и какими узлами могут быть связаны руки программистов. Поэтому в этом ключе мне не кажется это решение (постом выше) таким уж страшным (но это не дает нам повода думать, что с архитектурой тут все в порядке). Какие еще варианты я наблюдал при решении подобных ситуаций (в порядке убывания популярности):
1) Пишем макрос. Запихиваем портянку catch-й туда. Называем макрос CATCH_ALL и радуемся.
2) Делаем трансформацию DBException -> db_exception (наследник std::exception) и решаем задачу логирования единообразно, без портянок, на основе общности исключений. Потребует обертки оригинально API, который кидает кривые исключения, для обеспечения этого.
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
30
31
32
33
34
35
36
37
return_value good_exception_wrapper_for_db_api(arguments)
{
    try {
      //call third-party DB API
    }
    catch(const DBException& ex ) {
      // write some low-level logs, do rollback or whatever is needed
      throw transform_to_good(ex);
    }
}
 
class model {
private:
  void update_from_database() {
    try {
      //some code that calls third-party DB lib with good-exception wrapper
       good_exception_wrapper_for_db_api(...);
    }
    catch(const std::exception& ex ) {
      // write some low-level logs, do rollback or whatever is needed
      throw;
    }
    // Я убрал ветку catch(...) т.к. теперь мы предполагаем, что у нас в системе нет "левых" исключений
  }
 
  void store_to_database() {
    try {
      //other code that calls third-party DB lib with good-exception wrapper
    }
    catch(const std::exception& ex ) {
      // write some low-level logs, do rollback or whatever is needed
      throw;
    }
    // Я убрал ветку catch(...) т.к. теперь мы предполагаем, что у нас в системе нет "левых" исключений
  }
 
};
2
 Аватар для Voivoid
710 / 283 / 16
Регистрация: 31.03.2013
Сообщений: 1,340
27.02.2015, 09:48
Цитата Сообщение от DrOffset Посмотреть сообщение
ты предлагаешь учесть в этой задаче следующие ограничения:
Не, никаких особо ограничений нет. Суть в том, что есть несколько методов которые дергают некоторый API. Разные методы дергают разное подмножество API. API может кидать разные исключения ( в том числе и свои собственные, но они отнаследованы от std::exception ). Задача - обрабатывать эти исключения и выполнить в обработчике некоторые действия ( если речь скажем идет о БД, то это к примеру может быть роллбэк транзакции ). Причем естественно выполнить их сейчас, а не уровнем выше ( очевидно незачем эти подробности выносить ). И эти действия могут зависить от типа выброшенного исключения. Например для std::exception делаем rollback и пишем в лог. А для специфического БД исключения делаем rollback, пишем подробный лог и шедулим отправку письма админу СУБД

Цитата Сообщение от DrOffset Посмотреть сообщение
1) Пишем макрос.
Можно конечно, но с макросами всем известны проблемы

Цитата Сообщение от DrOffset Посмотреть сообщение
Делаем трансформацию DBException -> db_exception (наследник std::exception) и решаем задачу логирования единообразно
Придется писать лишние обертки

Цитата Сообщение от DrOffset Посмотреть сообщение
3) Твое решение с функтором.
Тоже на самом деле не всегда может помочь. Т.к. могут быть проблемы с возвратом результатов от API
0
19506 / 10109 / 2463
Регистрация: 30.01.2014
Сообщений: 17,833
27.02.2015, 13:51
Цитата Сообщение от Voivoid Посмотреть сообщение
Задача - обрабатывать эти исключения и выполнить в обработчике некоторые действия ( если речь скажем идет о БД, то это к примеру может быть роллбэк транзакции ). Причем естественно выполнить их сейчас, а не уровнем выше ( очевидно незачем эти подробности выносить ).
Согласен, незачем выносить. Но это касается только исключений от базы. Может тогда просто ловить только исключения от базы и делать с ними то, что специфично для базы (роллбэк и т.п.), а остальные пусть летят дальше. Зачем на уровне конкретного апи или конкретной модели (работа с БД) пытаться обработать все возможные варианты? Очевидно же, что это не тот уровень ответственности.

Цитата Сообщение от Voivoid Посмотреть сообщение
Например для std::exception делаем rollback и пишем в лог
А если там std::bad_alloc какой-нибудь? Если это не legacy и кода немного, то проще свести обработку в текущем месте к наиболее общему, подходящему под текущий уровень ответственности типу исключения. А всякие std::exception - это чересчур общий тип, чтобы на этом уровне вообще про него вспоминать. Если там внутри используются еще какие-то модели, с другой функциональностью, то отлавливать проблемы в них на их уровне.
0
 Аватар для Voivoid
710 / 283 / 16
Регистрация: 31.03.2013
Сообщений: 1,340
27.02.2015, 14:05
Цитата Сообщение от DrOffset Посмотреть сообщение
Может тогда просто ловить только исключения от базы и делать с ними то, что специфично для базы (роллбэк и т.п.), а остальные пусть летят дальше
Дык, остальные исключение тоже нельзя игнорировать. Если поддерживается strong exception guarantee, то rollback- нельзя не сделать ( ну если конечно выше уровнем мы не собираемся грохнуть всю программу ).

Цитата Сообщение от DrOffset Посмотреть сообщение
А если там std::bad_alloc какой-нибудь?
Ну это исключительное исключение Тут скорее всего вряд-ли уже чем поможешь.
0
19506 / 10109 / 2463
Регистрация: 30.01.2014
Сообщений: 17,833
27.02.2015, 14:18
Цитата Сообщение от Voivoid Посмотреть сообщение
Дык, остальные исключение тоже нельзя игнорировать.
Дык я не предлагаю их игнорировать. Их же можно обработать на своем уровне ответственности.
Ну я понял. Ты говоришь о том, что код написан так, что уровни слабо заизолированы друг от друга. И если при выполнении запроса к базе, после запроса какая-то вспомогательная система тоже дает сбой, то это в конечном итоге влияет на всю транзакцию и ее придется откатывать.

Добавлено через 2 минуты
Цитата Сообщение от Voivoid Посмотреть сообщение
Ну это исключительное исключение
Ну это пример, просто радикальный. Полно же исключений, которые к логике работы с БД никак не относятся. Я их имел в виду.
В целом я не считаю, что ты не прав (если это имеет для тебя значение). Т.е. мотивация и вариант решения мне понятны и не вызывают отторжения. Просто есть ощущение, что можно лучше
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
27.02.2015, 14:18

virtual PC
помогите пожалуйста. хочу изучать MWServer 2003. пытаюсь запускать virtual PC на компе(wind7,home basic 32-разяд) для практики,там сообш...

virtual
Всем привет. Есть вопрос по директиве virtual. Про нее...

Virtual в С++
Здравсвуйте программисты! Скажите пожалуйста какую роль играет в классах Virtual,как его использовать и зачем . В книге про него ни чего не...

Virtual Wi Fi.
Могу ли я, создав виртуальный wi fi адаптер (Беспроводное сетевое соединение 2), подключится к какому-либо соединению Wi Fi, при условии,...

virtual pc
подскажите,вот в папке где виртуальные машины раньше была кнопка типа &quot;создать виртуальную машину&quot;,щас же её уже нет,просто...


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

Или воспользуйтесь поиском по форуму:
56
Ответ Создать тему
Новые блоги и статьи
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ Основная суть и тезисы по измерениям: 0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема. Объект не может перемещаться в 0D. 1D (Первое измерение):. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru