2013-05-26 3 views
5

次のコードは、出力を136として示しています。しかし、最初の2つのアドレス比較がどのように等しいか理解できませんでした。これを理解する助けを感謝します。ありがとうございました。reintepret_castでオブジェクトアドレスを解釈する

#include <iostream> 

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; 
A *b1 = &d; 
B *b2 = &d; 

const int a = (reinterpret_cast<char *>(b1) == reinterpret_cast<char *>(&d)) ? 1 : 2; 
const int b = (b2 == &d) ? 3 : 4; 
const int c = (reinterpret_cast<char *>(b1) == reinterpret_cast<char *>(b2)) ? 5 : 6; 

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

return 0; 
} 
+1

なぜここで 'reinterpret_cast'を使用していますか?あなたのアーキテクチャのポインタ型に 'char * 'を使うと何が期待されますか? –

+0

これはリアルタイムアプリケーションからのものではありません。これはC++テストからのものです。私はreinterpret_castがこの特定のケースでどのようにアドレスを解釈しているかを理解したいだけです。 – irappa

答えて

1

例のように複数の継承を使用する場合、最初の基本クラスと派生クラスは同じ基本アドレスを共有します。継承した追加のクラスは、先行するすべてのクラスのサイズに基づいたオフセットで順番に並べられます。 db1のベースアドレスが同じであるため、比較の結果は真です。

Aのサイズが4バイトの場合、Bは、A + 4バイトのベースアドレスから開始します。 B *b2 = &d;を実行すると、コンパイラはオフセットを計算し、それに応じてポインタ値を調整します。

b2 == &dを実行すると、比較が行われる前に、タイプ 'C'からタイプ 'B'への暗黙的変換がdで実行されます。この変換は、割り当て時と同じようにポインタ値のオフセットを調整します。

+0

ありがとうございます。しかし、どのようにb2 ==&d? – irappa

+0

答えが更新され、その結果が真になる理由に関する情報が追加されました –

0

それはその2つの基底クラス(AB)で始まり、そのタイプCのインスタンスのアドレスが同じになるので、それがメモリにレイアウトされる(ここでのようなC)派生クラスのためにかなり典型的ですインスタンスの最初の基本クラス(すなわちA)のアドレス。

0

継承このような(virtualが関与していない)でCの各インスタンスは、以下のレイアウトがあります:

  • まず、ちょうどm_iである(4 Aのすべてのメンバーが存在するであろう-byte整数)
  • セカンド最終だけで文字(1バイト、である、C自体のすべてのメンバーになりますBのすべてのメンバー(ちょうどm_dで、8バイトのダブル)
  • になります)
  • Aが最初の親であるので、あなたは、 ACのインスタンスへのポインタをキャスト

、何のアドレスの調整は行われず、二つのポインタの数値が同じになります。これは、最初の比較がtrueと評価される理由です。 (reinterpret_cast<char *>()をポインタに置くと、調整が行われないので、常にポインタの数値が返されることに注意してください。void *にキャストすると同じ効果があり、おそらく比較のために安全です)。

インスタンスへのポインタのキャストCBb2の数値は、&dに等しくならないであろうことを意味する(4バイト)ポインタ調節を引き起こすであろう。ただし、b2&dを直接比較すると、コンパイラによって自動的に&dB *のキャストが生成され、数値が4バイト調整されます。これは、2回目の比較もtrueと評価される理由です。

第比較リターンfalseB *にないキャスト中A *にキャストすると、調整を行わない。)AまたはBCのインスタンスへのポインタをキャストすると、異なる結果を有することになる、前に述べたように

、なぜなら
+0

レイアウトはコンパイラに依存します。あなたが説明したものは典型的なものですが、どこにでも義務化されていません。 – EJP

+0

@EJPそうです!しかし、OPは彼がコンパイルしたコードで見ている動作を説明する人を求めていた。私はちょうどそれをやっていた。私はこれが標準によって義務づけられていると主張していない。私はちょうど彼のプログラムの出力がどんなものになったか説明しています。 – yzt