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 ませんが、それを使用すると形式が正しくなくなり、結果としてコンパイラエラー。これを使用するとnullポインタが生成されるためではありません。そしてもちろん、テキストが説明しているコードは間違いなく 正しいです。

間違いが起こります-多分それは本の第4版で修正されるでしょう。:-]

(また、をBB_ival_slider宣言fするとfriend、コード本で説明されているように動作することに注意してください。おそらくこのfriend宣言はこの章の前半で暗示されていましたが、今は注意深く読んで一方向を確認する時間がありません。またはその他。)

于 2011-08-26T21:26:46.330 に答える
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'ます。他のコンパイラ:誰が知っていますか?私が知っているすべてのコンパイラには、標準への準拠に問題があります。

于 2011-08-26T20:43:46.330 に答える
0

建設的な証拠が見つからない場合は、

「ストロヴルプが間違っていた」(怖いですね:()

私は、コンパイラーがクラスの内臓を喜んで(定義された標準によって)内部にこぼすことを許可されているとは思いません。彼らがナイフに通されない限り。(つまり、邪悪なポインタ操作)

于 2011-08-26T21:09:43.890 に答える