динамический сомнение из C++/Страуструп: преобразование защищенного базового класса
Я знаю, что следующий код дает ошибку компиляции:
class A{ public : virtual void name(){cout<<typeid(this).name()<<endl;}; };
class B:protected A{public : virtual void name(){cout<<typeid(this).name()<<endl;};};
void foo(B* b)
{
A * a = dynamic_cast<A*>(b); //Error : 'A' is an inaccessible base of 'B'
return;
}
, но тогда почему в книгу по c++ Страуструп (15.4.1) он пишет
class BB_ival_slider:public Ival_slider,protected BBslider{ //...
};
void f(BB_ival_slider*p)
{
// ok
BBslider* pbb2 = dynamic_cast<BBslider*>(p); // ok: pbb2 becomes 0
}
Не должна ли строка быть ошибкой компиляции ? Так что либо мой gcc ошибается, помечая его как ошибку компиляции, либо немыслимую опечатку строструпа, либо, скорее всего, я что-то пропустил...
3 ответа:
Фактическая цитата из 15.4.1 такова:
Таким образом, казалось бы, что текст, описывающий код, является правильным, но по неправильным причинам --class BB_ival_slider : public Ival_slider, protected BBslider { // ... }; void f(BB_ival_slider* p) { Ival_slider* pi1 = p; // ok Ival_slider* pi2 = dynamic_cast<Ival_slider*>(p); // ok BBslider* pbb1 = p; // error: BBslider is a protected base BBslider* pbb2 = dynamic_cast<BBslider*>(p); // ok: pbb2 becomes 0 }
Это неинтересный случай. Тем не менее, это обнадеживает знать, что
dynamic_cast
не допускает случайного нарушения защиты частных и защищенных базовых классов .dynamic_cast
не допускает случайного нарушения защиты частных и защищенных базовых классов, но только потому, что его использование это будет неправильно сформировано и приведет к ошибке компилятора, а не потому, что его использование приведет к нулевому указателю. И, конечно, код, который описывает текст, определенно в правильно. Ошибки случаются - может быть, это будет исправлено в 4-м издании книги. :- ](Также обратите внимание, что если
BB_ival_slider
объявляетf
friend
, то код будет вести себя так, как описано в книге. Возможно, этоfriend
заявление подразумевалось ранее в этой главе, но я у меня сейчас нет времени внимательно его перечитывать, чтобы проверить в ту или иную сторону.)
Возможно, он проверял этот код, возможно, нет. (Многие авторы помещают непроверенный код в свои книги.) Если он действительно тестировал его, имейте в виду, что не все компиляторы созданы равными. g++ завершается с ошибкой
error: 'BBslider' is an inaccessible base of 'BB_ival_slider'
. clang терпит неудачу сerror: cannot cast 'BB_ival_slider' to its protected base class 'BBslider'
. Другие компиляторы: кто знает? Каждый компилятор, о котором я знаю, имеет некоторые проблемы с соответствием стандарту.
Я думаю, что если я не нахожу никаких конструктивных доказательств, то я мог бы просто сказать
"Строструп был неправ" (это звучит страшно : ()
Я не думаю, что компиляторам позволено выплескивать внутренности внутреннего класса добровольно (по определенному стандарту). Если только их не проткнуть ножом. (злая операция указателя, то есть)