Тип объекта исключения, созданного выражением исключения

Я прочитал следующее из C++ Primer (5-е издание, раздел 18.1.1): «Когда мы выбрасываем выражение, статический тип времени компиляции этого выражения определяет тип объекта исключения».

Под "типом объекта исключения" автор подразумевает динамический тип или статический тип объекта исключения?

Вот связанный с этим вопрос: Статический тип объекта исключения


person yuanlu0210    schedule 22.10.2017    source источник


Ответы (1)


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

Во-первых, когда в игру вступают статические и динамические типы? Ответ — полиморфизм во время выполнения. Теперь, хотя вы, возможно, слышали выражение «полиморфные типы», вы должны знать, что такого понятия не существует. Типы не полиморфны.

Но их можно использовать полиморфно! Это различие важно, и я надеюсь, вы скоро поймете, почему. Давайте рассмотрим простой кейс:

struct Base {
  virtual void print() const { std::cout << "Base"; }
};

struct Derived : Base {
  void print() const override { std::cout << "Derived"; }
};

void foo(Base& b) {
  b.print();
}

int main() {
  Derived d;
  foo(d);
}

Внутри foo мы можем использовать ссылку b, которая привязана к некоторому объекту Base. Каков тип выражения b? Это Base. Потому что, если бы мы создали копию объекта, на который делается ссылка, мы бы получили Base. Это так называемый статический тип объекта. Тот тип, что прописан в декларации, простой и понятный. Кроме того, внутри main какой тип d? Это Derived по той же причине.

Но что происходит, когда вы передаете d в foo?

К нему привязывается ссылка b, что, конечно, разрешено. Это "настоящий", динамический тип, Derived. Но foo относится к нему с помощью Base&. Вот что такое полиморфное использование. Несмотря на то, что функция видит один тип, на самом деле это другой. И из-за косвенности это «другой» тип, с которым работают через механизм виртуальной функции.

Теперь давайте применим это к вашему вопросу. Бросание сделает копию объекта. Тип копируемого объекта определяется заданным выражением. Поэтому, когда вы дадите ему Base&, он создаст объект Base. Тот факт, что это могла быть ссылка на Derived, не имеет значения. Создание исключения не является полиморфным использованием.

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

person StoryTeller - Unslander Monica    schedule 22.10.2017
comment
Спасибо (особенно за иллюстрацию полиморфного использования)! Я почему-то думал, что выбрасывание объекта-исключения таким образом исключает возможность динамического связывания. - person yuanlu0210; 23.10.2017