static_cast и ссылка на указатели

Может ли кто-нибудь сказать мне, почему это не компилируется:

struct A { };
struct B : public A { };

int main()
{
  B b;
  A* a = &b;
  B* &b1 = static_cast<B*&>(a);
  return 0;
}

Теперь, если вы замените статическое приведение на:

B* b1 = static_cast<B*>(a);

тогда он компилируется.

Редактировать: очевидно, что компилятор обрабатывает A* и B* как независимые типы, иначе это сработало бы. Вопрос больше в том, почему это желательно?


person PierreBdR    schedule 17.01.2013    source источник
comment
a не является ссылкой на указатели, это указатель.   -  person andre    schedule 17.01.2013
comment
@MrLister B*& — это ссылка на указатель на B.   -  person Some programmer dude    schedule 17.01.2013
comment
К вашему сведению, dynamic_cast было бы безопаснее.   -  person dchhetri    schedule 17.01.2013
comment
@user814628 user814628 Только в том случае, если вы не знаете (из-за логики программы), что приведение допустимо, и использование dynamic_cast заставляет компилятор встраивать информацию о типе времени выполнения в эту иерархию классов. Объедините это с относительно медленной работой dynamic_cast, и вы не захотите использовать это решение, если в этом нет необходимости.   -  person Agentlien    schedule 17.01.2013
comment
@user814628 user814628 dynamic_cast здесь недопустимо.   -  person James Kanze    schedule 17.01.2013


Ответы (4)


B является производным от A, но B* не является производным от A*. Указатель на B не является указателем на A, его можно преобразовать только в единицу. Но типы остаются разными (а преобразование может и часто будет изменять значение указателя). B*& может ссылаться только на B*, а не на любой другой тип указателя.

person James Kanze    schedule 17.01.2013

неконстантная ссылка lvalue (B*&) не может быть связана с несвязанным типом (A*).

person Community    schedule 17.01.2013

Вы пытаетесь преобразовать A* в B*. Это неправильный путь и не очень полезный. Вы, вероятно, захотите сохранить указатель на производный в указателе на базу, что полезно и даже не требует приведения.

Я предполагаю, что здесь может работать dynamic_cast, но результат определяется реализацией, если я не ошибаюсь.

person rubenvb    schedule 17.01.2013
comment
Вы не можете использовать dynamic_cast для преобразования A* в B*&. Это не законно, и код не скомпилируется. - person James Kanze; 17.01.2013
comment
Приведение от A* к B* — единственное направление, в котором static_cast имеет смысл. В другом направлении делать нечего. - person PierreBdR; 17.01.2013

Обработка ссылок - это то, что компилятор делает за вас, не должно быть необходимости приводить к ссылке.

Если мы рефакторим код, чтобы:

B b;
A* a = &b;
B* b_ptr = static_cast<B*>(a);
B*& p1 = b_ptr;

Он будет компилироваться.

person Periodic Maintenance    schedule 17.01.2013
comment
Я согласен (см. мой пост), но это не то же самое. Например, изменение указателя в p1 не меняет указатель в a. - person PierreBdR; 17.01.2013