为什么指向同一结构体不同成员的指针成员的值始终相同?

11

我有以下代码:

#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 的类型是什么?我猜它应该是 指向字符串 foo_s 成员的指针
  2. 为什么 field 的值总是相同的(本例中为1),而 foo->*field 却得到不同的结果?

主要困惑于第二点。我原以为 field 是从结构体开头的“偏移量”,而 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的值在调用中没有变化。我错过了什么?标准具体描述了这个操作的方式是什么?

2个回答

18

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

为了进一步说明,您可以首先尝试流传递boolalpha;然后您应该看到true而不是1


2
哇,这教会了我要坚持使用好老的printf,即使只是因为我更理解它。 - martin
5
如果您尝试打印一个成员指针,那么这将导致未定义行为。C++输入/输出至少是类型安全的,尽管有时会令人困惑。 - Mike Seymour
1
@martin 有趣的问题 - 您打算使用哪种格式说明符来指定成员指针?一般来说,您甚至不知道这个东西的大小。 - Angew is no longer proud of SO
1
@Angew 哦,也许我应该停止写代码了……对于其他感兴趣的读者,这里是参考链接:https://dev59.com/VW_Xa4cB1Zd3GeqP6ORt。 - martin
啊!谢谢,那很有道理。当将指针转换为int时,static_cast触发了编译时错误,我应该明白这是怎么回事。 - anthonyvd

7
  1. field的类型,就像您所说的一样,是指向foo_s中类型为std::string的成员的指针。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接