динамический сомнение из 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 3

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'. Другие компиляторы: кто знает? Каждый компилятор, о котором я знаю, имеет некоторые проблемы с соответствием стандарту.

Я думаю, что если я не нахожу никаких конструктивных доказательств, то я мог бы просто сказать

"Строструп был неправ" (это звучит страшно : ()

Я не думаю, что компиляторам позволено выплескивать внутренности внутреннего класса добровольно (по определенному стандарту). Если только их не проткнуть ножом. (злая операция указателя, то есть)