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

时间:2015-05-15 14:48:41

标签: c++ language-lawyer pointer-to-member

我有以下代码:

#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会产生不同的结果?
  3. 主要是,我对#2感到困惑。我想象的领域将是一个&#34;偏移&#34;从结构的开头,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 个答案:

答案 0 :(得分:18)

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

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

答案 1 :(得分:7)

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

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