来自C ++ / Stroustrup的dynamic_cast疑问:转换为受保护的基类

时间:2011-08-26 20:36:42

标签: c++ inheritance dynamic-cast

我知道以下代码会出现编译错误:

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在将其标记为编译错误或者不可思议的,stroustrup错误或者最合理的错误我错过了什么......

3 个答案:

答案 0 :(得分:2)

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声明ffriend,则代码的行为与书中所述相同。也许这样{本章前面已经隐含了{1}}声明,但我现在没有时间仔细阅读以检查这种或那种方式。)

答案 1 :(得分:0)

也许他测试了那些代码,也许不是。 (许多作者将未经测试的代码放入他们的书中。)如果他测试了它,请记住并非所有编译器都是平等的。 g ++以error: 'BBslider' is an inaccessible base of 'BB_ival_slider'失败。 clang以error: cannot cast 'BB_ival_slider' to its protected base class 'BBslider'失败。其他编译器:谁知道?我所知道的每个编译器在符合标准方面都存在一些问题。

答案 2 :(得分:0)

我想如果我没有找到任何建设性的证据,那么我可以说

“Stroustrup错了”(听起来很吓人:()

我不认为编译器可以自愿地(通过定义的标准)泄漏内部类的内容。除非他们是通过刀。 (邪恶的指针操作)