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

Virtual и noreturn

23.02.2015, 19:57. Показов 10588. Ответов 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
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,818
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
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,818
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
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,818
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
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,818
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
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,818
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
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,818
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
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,818
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
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,818
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
Ответ Создать тему
Новые блоги и статьи
Переходник USB-CAN-GPIO
Eddy_Em 20.03.2026
Достаточно давно на работе возникла необходимость в переходнике CAN-USB с гальваноразвязкой, оный и был разработан. Однако, все меня терзала совесть, что аж 48-ногий МК используется так тупо: просто. . .
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
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 и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru