2012-09-20 8 views
9

誰でも次のコードの動作を説明できますか?アドレス、reinterpret_castと複数の継承

  1. 最初のケースではb = 3、つまりb2 == &dは本当ですか?
  2. なぜケース2では大丈夫ですか?私はb2dのアドレスを印刷してあり、それらは異なっています。
#include <iostream> 

using namespace std; 

class A 
{ 
public: 
    A() : m_i(0) { } 

protected: 
    int m_i; 
}; 

class B 
{ 
public: 
    B() : m_d(0.0) { } 

protected: 
    double m_d; 
}; 

class C 
    : public A 
    , public B 
{ 
public: 
    C() : m_c('a') { } 

private: 
    char m_c; 
}; 

int main() 
{ 
    C d; 
    B *b2 = &d; 

    cout << &d << endl; 
    cout << b2 << endl; 

    const int b = (b2 == &d) ? 3 : 4; ///Case1: b = 3; 
    const int c = (reinterpret_cast<char*>(b2) == reinterpret_cast<char*>(&d)) ? 3 : 4; //Case 2: c = 4; 

    std::cout << b << c << std::endl; 

    return 0; 
} 
+0

+1これは良い例であり、ポインタへの多重継承の影響を非常によく示しているからです。 – ltjax

+0

+1同様です。素晴らしい例です。特に、実際にはリンガーを介して人々を送るためのバーチャルはありません。 – WhozCraig

答えて

9

Dを使用して、BへのポインタをCへのポインタを変換すると、それは(例えばajustementが一般的に必要とされるCのBサブオブジェクトを指すように、それを調整するタイプCのあります複数の継承では、Bに必要なものがなければ、AとBの両方から継承したCのようなものがあります)。したがって、割り当ておよび比較時に、調整が行われる。

& dは、void *(暗黙的)またはchar *(reinterpret_cast)のいずれかに変換され、調整は行われません(reinterpret_castを使用して明示的に調整を求めないため、ボイド*に変換するときに調整してください。正直でない理由で往復を複雑にするだけですが、Aと同じような結果になりますので、表現が異なります。

reinterpret_cast<B*>(&d)を使用していた場合は、再度調整は行われませんでしたが、結果をB *として使用すると、すぐに問題が発生します。

3

ケース1では、比較によって自動的にCポインタがBポインタにキャストされます。この場合、これは、複数の継承を使用し、Bが基本クラスのリストで2番目であるため、実際のアドレスが変更されることを意味します。具体的には、ポインタは(少なくとも)sizeof(A)だけオフセットされなければならない。しかしながら、第2の場合、そのような自動変換は行われないので、 "A接頭辞"は2つのポインタを不等にする。

+0

「自動キャスト」のようなものはありません。キャストは明示的な変換であり、ソースコード内に存在します。 – curiousguy

+0

それはどういう意味ですか?明らかに、ケース1ではアップキャストがありますが、明示的ではありません。 – ltjax

+0

明示的でないキャストは、単にキャストされません。キャストは、Cスタイル、機能スタイル、または新しいスタイルにすることができます: '(T)x'、' T(x) '、' static_cast (x) '... – curiousguy