dynamic_cast сомнения из C ++ / Stroustrup: преобразование в защищенный базовый класс - PullRequest
3 голосов
/ 27 августа 2011

Я знаю, что следующий код выдает ошибку компиляции:

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 ]

2 голосов
/ 27 августа 2011

Фактическая цитата из 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 подразумевалось ранее в глава, но у меня сейчас нет времени, чтобы внимательно прочитать ее, чтобы проверить, так или иначе.)

0 голосов
/ 27 августа 2011

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

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

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

0 голосов
/ 27 августа 2011

Возможно, он проверял этот код, а может и нет. (Многие авторы помещают непроверенный код в свои книги.) Если он проверял его, имейте в виду, что не все компиляторы созданы равными. g ++ не работает с error: 'BBslider' is an inaccessible base of 'BB_ival_slider'. лязг не удается с error: cannot cast 'BB_ival_slider' to its protected base class 'BBslider'. Другие компиляторы: кто знает? У каждого известного мне компилятора есть проблемы с соответствием стандарту.

...