dynamic_cast сомнение в C++/Stroustrup: преобразование в защищенный базовый класс
Я знаю, что следующий код дает ошибку компиляции:
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++ Stroustrup (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'
, лязг терпит неудачу с error: cannot cast 'BB_ival_slider' to its protected base class 'BBslider'
, Другие компиляторы: кто знает? У каждого известного мне компилятора есть проблемы с соответствием стандарту.