为什么指向成员的指针的值对于同一结构的不同成员总是相同的?

Why is the value of a pointer-to-member always the same for different members of the same struct?

我有以下代码:

#include <iostream>
#include <string>

using namespace std;

struct foo_s {
    string a;
    string b;
    string c;
};

void print_field(foo_s* foo, string foo_s::* field) {
    cout << "field: " << field << " - " << foo->*field << endl;
}

int main() {
   foo_s my_foo = {
       "a",
       "b",
       "c",
   };

   print_field(&my_foo, &foo_s::a);
   print_field(&my_foo, &foo_s::b);
   print_field(&my_foo, &foo_s::c);

   return 0;
}

它的输出是:

field: 1 - a                                                                                                                                                                                                              
field: 1 - b                                                                                                                                                                                                              
field: 1 - c  

我在理解 print_field() 函数中发生的事情的具体细节时遇到了一些困难。即:

  1. field 的类型是什么?我想是 pointer-to-string-foo_s-member
  2. 为什么 field 的值总是相同(在本例中为 1),而 foo->*field 却产生不同的结果?

主要是,我对#2 感到困惑。我想象字段从结构的开始是一个 "offset" 并且 foo->*field 在概念上等同于

char* ptr = static_cast<char*>(foo);
ptrdiff_t offset = somehow_get_the_byte_offset_from_pointer_to_member(field);
ptr = ptr[offset];
string result = *static_cast<string*>(ptr);

但这似乎已经过时了,因为 field 的值不会因调用而异。我错过了什么?这个具体的操作,标准是怎么描述的?

<< 没有重载来格式化成员指针的值,因此即使您尝试也不会得到任何特别有用的东西。 bool 有一个重载,成员指针可以转换为 bool,所以这就是这里发生的事情。指针不为空,因此它转换为 true,默认情况下格式为 1.

为了进一步演示,您可以先尝试流式传输 boolalpha;那么你应该看到 true 而不是 1.

  1. field的类型,如你所说,是指向foo_s类型std::string的成员的指针。

  2. 在所有这些情况下field的值都是1,因为指向成员的指针可以转换为bool,所以当你输出它们时,你得到一个 1 因为它们不为空。