1

非常に奇妙な問題に遭遇しました。これの理由を知っている人はいますか? コードは Visual Studio 2012 でテストされています。

#include <iostream>
struct A {
  int a;
};
struct B {
  int b;
};
struct C : public A, public B {
  int c;
};

int main() {
  int C::*p = &C::b;
  std::printf("%p\n", &C::b); //00000000
  std::printf("%p\n", p);     //00000004
  return 0;
}
4

2 に答える 2

2

メンバーへのポインターは単純な C ポインターではないため、それらを に渡すことはprintf実際には未定義の動作です。printf"%p"void*

標準で許可されているメンバーへのポインターの唯一の変換は、段落 4.11 にリストされています。

  1. null ポインター定数は null メンバー ポインター値に変換できます。
  2. B::*TD::*TB が D のアクセス可能で、あいまいでなく、非仮想の基底クラスである場合、に変換できます。

メンバーへのポインターは、実際には、それらが指しているクラスに応じて異なるサイズを持つことができます。

MSVC でのポインターからメンバーへの実装の詳細については、http: //blogs.msdn.com/b/oldnewthing/archive/2004/02/09/70002.aspxを参照してください。

于 2013-08-29T12:01:54.310 に答える
0

次の予期しない結果に注意してください。

printf("typeid(&C::b) = %s\n",typeid(&C::b).name());
printf("typeid(&B::b) = %s\n",typeid(&B::b).name());

VS2010で得られるのは次のとおりです。

typeid(&C::b) = int B::*
typeid(&B::b) = int B::*

これは、&C::b の結果の型が型 B のメンバー ポインターであることを示しています。C は B から派生しているため、ポインターは型 C のメンバー ポインターに自由に変換できます。これにより、表示される 2 つの値の違いが説明されます。&C::b は B 型のメンバー関数ポインターであり、int C::*p は C 型のメンバー関数ポインターです。

int B::*p_b = &B::b;
int C::*p_c = p_b;
printf("p_b = %p\n", p_b);
printf("p_c = %p\n", p_c);
于 2013-08-29T16:32:54.797 に答える