Обоснование броска статического типа? - PullRequest
7 голосов
/ 20 апреля 2011

Согласно FAQ C ++ , когда кто-то бросает объект, он генерируется с использованием выражения static .Следовательно, если у вас есть:

catch ( some_exception const &e ) {
  // ...
  throw e; // throws static type, possibly causing "slicing"; should just "throw;" instead
}

и e - это на самом деле ссылка на некоторый класс, производный от some_exception, приведенный выше throw приведет к тому, что объект будет "нарезанный "тихо.Да, я знаю, что правильный ответ просто на throw;, но то, как все выглядит, кажется ненужным источником путаницы и ошибок.

В чем причина этого?Почему не вы хотите, чтобы он генерировал объект динамический ?

Ответы [ 3 ]

9 голосов
/ 20 апреля 2011

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

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

4 голосов
/ 20 апреля 2011

«Аргумент» для throw является выражением, и именно тип выражения определяет тип создаваемого объекта исключения.Тип брошенного выражения не обязательно должен быть полиморфным типом, поэтому не может быть способа определить, действительно ли выражение относится к подобъекту базового класса более производного типа.

"Более простой"Тип выражения «правило» также означает, что реализация не должна динамически определять размер и тип объекта исключения во время выполнения, что может потребовать создания более сложного и менее эффективного кода для обработки исключений.Если бы он должен был сделать это, он представлял бы единственное место в языке, где требовался конструктор копирования для типа, неизвестного в точке вызова.Это может значительно увеличить стоимость реализации.

0 голосов
/ 21 апреля 2011

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

struct foo {};

struct ncfoo : foo
{
private:
    ncfoo(ncfoo const&) {}
};

ncfoo g_ncfoo;

void fun()
{
    foo& ref = g_ncfoo;
    throw ref; // what should be thrown here?
}

Если вы скажете «в этом случае просто выбросьте статический тип», то каковы точные правила - что означает «в этом случае»? Ссылки, которые мы только что перехватили, «перебрасываются» без копирования, все остальное копируется? Хм ...

Но как бы вы ни определяли правило, оно все равно будет сбивать с толку. Бросок ссылки может привести к другому поведению, в зависимости от того, откуда мы получили эту ссылку. Нех. C ++ уже сложен и достаточно запутанен:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...