9

次のコードの動作を説明できる人はいますか?

  1. なぜb = 3最初のケースで、つまりb2 == &dtrue なのですか?
  2. ケース 2 でなぜ OK なのですか? b2とのアドレスを印刷しましたがd、それらは異なります。
#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;
}
4

2 に答える 2

9

dはタイプCです。CへのポインタをBへのポインタに変換すると、CのBサブオブジェクトを指すように調整されます(Bに何も必要ない場合は、一般に複数の継承でこのような調整が必要です。 CはAとBの両方から継承するため、A用に1つあります)。したがって、割り当てと比較の時点で、調整が行われます。

他の2つの場合、&dはvoid *(暗黙的に)またはchar *(reinterpret_castを使用)のいずれかに変換され、調整は行われません(reinterpret_castで調整を行わないように明示的に要求し、変換時に調整を行う理由はありません) void *にすると、正当な理由もなく往復が複雑になります。A)についても同様の結果が得られるため、表現が異なります。

ところで、もし使っていたら、reinterpret_cast<B*>(&d)二度と調整はされなかったでしょうが、結果をB *として使うと、すぐに問題が発生します。

于 2012-09-20T12:12:01.633 に答える
3

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

于 2012-09-20T12:12:16.847 に答える