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"和 C 将指向成员的指针转换为void*.

标准允许的成员指针的唯一转换列在第 4.11 段中:

  1. 空指针常量可以转换为空成员指针值
  2. B::*TD::*T如果 B 是 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 类型的成员指针。这解释了您看到的两个值之间的差异。&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 回答