указатель std :: bad_cast против эталонной ситуации - PullRequest
2 голосов
/ 23 февраля 2012

В отношении исключения std :: bad_cast я заметил, что ссылки и указатели, похоже, не работают одинаково.Например:

class A { public: ~A() {} };
class B : public A {};

//Case #1
int main()
{
    A a;
    B& b = dynamic_cast<B&>(a);  //Would throw std::bad_cast.
}

//Case #2
int main()
{
    A* a = new A;
    B* b = dynamic_cast<B*>(a);  //Would not throw std::bad_cast.
}

В первом случае генерируется исключение std :: bad_cast, а во втором случае исключение не создается - вместо этого указателю b просто присваивается значение NULL.

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

Ответы [ 2 ]

6 голосов
/ 23 февраля 2012

Может кто-нибудь объяснить мне, почему только первый бросает исключение?

Вот как dynamic_cast определено для поведения: плохое dynamic_cast с указателями приводит к нулевому указателю, но нулевых ссылок нет, поэтому плохое dynamic_cast с использованием ссылок выдает bad_cast.

Тот факт, что неудачный dynamic_cast с указателями приводит к нулевому указателю, полезен, поскольку он обеспечивает более чистую и простую проверку типов и допускает следующую идиому:

if (B* b = dynamic_cast<B*>(a))
{
    // The dynamic_cast succeeded and 'b' is non-null.
}

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

2 голосов
/ 23 февраля 2012

Ссылки должны быть связаны с объектом, который содержит действительный адрес памяти ... они не могут быть "неинициализированными", и при этом они не имеют значений инициализации по умолчанию без привязки. Обратите внимание, что раздел 8.5 / 8 в стандартных состояниях C ++ 11,

Программа, которая вызывает инициализацию по умолчанию или инициализацию значения объекта ссылочного типа, неверна.

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

Таким образом, если по стандарту операция dynamic_cast<T&> должна возвращать действительный адрес памяти для привязки к ссылочной переменной, то, если динамическое приведение завершится неудачно, она не сможет вернуть «не-значение» ... единственный вариант это бросить исключение.

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