我知道以下代码会出现编译错误:
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错误或者最合理的错误我错过了什么......
答案 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
声明f
为friend
,则代码将的行为与书中所述相同。也许这样{本章前面已经隐含了{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错了”(听起来很吓人:()
我不认为编译器可以自愿地(通过定义的标准)泄漏内部类的内容。除非他们是通过刀。 (邪恶的指针操作)