Question

Meet a very weird problem, anyone know what is the reason of this? the code is tested under 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;
}
Was it helpful?

Solution 2

Note the possibly unexpected result of:

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

Which on VS2010 yields:

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

This indicates that the resulting type for &C::b is a member pointer on type B. Since C is derived from B the pointer is freely convertible to a member pointer on type C. This explains the difference between the two values you see. &C::b is a member function pointer on type B, int C::*p is a member function pointer on type 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);

OTHER TIPS

Pointers to members are not just plain C-pointers, so passing them to printf is actually undefined behavior, because printf will believe in the "%p" and C-cast the pointer-to-member to void*.

The only conversions of pointers to members allowed by the standard are listed in paragraph 4.11:

  1. Null-pointer constants can be converted to null member pointer values
  2. B::*T can be converted to D::*T if B is an accessible, nonambiguos and nonvirtual baseclass of D.

Pointers to members can actually have different sizes depending on the classes they point into.

See here for more info on pointer-to-member implementations in MSVC: http://blogs.msdn.com/b/oldnewthing/archive/2004/02/09/70002.aspx

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top