2011-08-26 51 views
3

我知道下面的代码提供的编译错误: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 
} 

不应该是编译错误? 因此,无论我的海湾合作委员会是错误的标记为编译错误或不可思议,stroustrup错字或最振振有词我错过了...

+0

有趣的问题 - 请注意,即使基础是虚拟的,并且子子类通过“public virtual”从同一个基础派生...我希望看到一个关于编译器为什么拒绝这个的C++标准引用。 – bdonlan

+0

我很懒。 :(我通常按照Stroustrup的话作为标准。:) 但我认为有必要为这样一种生动的语言打开这个世界上最枯燥无味的标准报告。 –

+3

@bdonlan:5.2。关于'dynamic_cast (pointer_to_class_D)'说'B'应该是一个**可访问的**明确的D类基类(重点是我的)。 –

回答

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允许偶然违反private和protected基类的保护,但这仅仅是因为使用它会不合格,并会导致编译器错误,而不是因为使用它会产生空指针。当然,文中描述的代码是绝对是正确。

错误发生 - 可能会在本书的第4版中修复。 : - ]

(另请注意,如果BB_ival_slider声明f是一个friend,那么代码将在书中描述的也许这friend宣言本章前面暗示,但我不的行为。现在有时间仔细阅读,以检查其中一种方式。)

+0

哇,我很想掌握你用来从书中复制那些内容的任何东西。你有什么 ? PDF或一些电子书? –

+0

@Ajeet:我看了我的硬拷贝并输入了它,因为它很短。如果我有一本电子书,我可以在章节中搜索“朋友”一词,并回答我最后一段中提出的问题。 ; - ] – ildjarn

+0

很酷,你是我的类型,他的桌面上能让Stroustrup保持在手中吗? –

0

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

+1

恩,我们在这里讨论stroustrup .... 标准反映了他的想法。反之亦然。 :P –

+0

好吧错读了Q. –

0

我想,如果我没有发现任何证据表明建设性的话,我可能只是说

“斯特劳斯错了”(这听起来吓人:()

我不认为编译器被允许溢出的胆量。类内部心甘情愿(由定义的标准),除非他们通过刀放(邪恶的指针操作即是)

+0

通过“邪恶指针操作”,我认为你的意思是邪恶的C式演员。是的,C风格的类型转换可以将派生类指针转换为基类指针,“*即使基类不可访问*”(5.4第7段)。这个邪恶操作的结果不是空指针。 –

+0

@大卫是的,是的。这种C式黑魔法根本无法治愈。 :) 如果有人使用过它,那么只有“施放”它的人才能够可靠地撤消它。 hehehe –