3

我知道以下代码会产生编译错误:

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 错字,或者最有可能我错过了一些东西......

4

3 回答 3

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为 a friend,那么代码按照书中描述的方式运行。也许friend本章前面已经暗示了这个声明,但我现在没有时间仔细阅读它以检查一种方式或其他。)

于 2011-08-26T21:26:46.330 回答
0

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

“Stroustrup 错了”(这听起来很可怕 :( )

我不认为编译器可以随意泄露类内部的内容(按照定义的标准)。除非他们被刀刺穿。(即邪恶的指针操作)

于 2011-08-26T21:09:43.890 回答
0

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

于 2011-08-26T20:43:46.330 回答