2015-05-15 24 views
11

Tôi có đoạn mã sau:Tại sao giá trị của một con trỏ đến thành viên luôn giống nhau cho các thành viên khác nhau của cùng một cấu trúc?

#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; 
} 

đầu ra của nó là:

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

Tôi đang gặp một chút rắc rối tìm hiểu những đặc trưng của những gì đang xảy ra trong print_field() chức năng. Cụ thể:

  1. Loại field là gì? Tôi tưởng tượng nó là pointer-to-string-foo_s-member
  2. Tại sao giá trị của field luôn giống nhau (1 trong trường hợp này), nhưng foo->*field cho kết quả khác nhau?

Chủ yếu, tôi bị bối rối ở # 2. Tôi tưởng tượng lĩnh vực sẽ được một "bù đắp" từ khi bắt đầu của cấu trúc và foo->*field sẽ là khái niệm tương đương với một cái gì đó giống như

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); 

nhưng điều đó có vẻ là ra vì giá trị field 's không khác nhau giữa các cuộc gọi. Tôi đang thiếu gì? Làm thế nào chính xác là hoạt động cụ thể này được mô tả theo tiêu chuẩn?

Trả lời

18

Không có quá tải cho << để định dạng giá trị của con trỏ thành viên, vì vậy bạn sẽ không nhận được bất kỳ điều gì đặc biệt hữu ích nếu bạn thử. Có quá tải cho bool và các con trỏ thành viên có thể chuyển đổi thành bool, vì vậy đó là những gì xảy ra ở đây. Con trỏ không phải là null, do đó, nó chuyển đổi thành true, theo mặc định được định dạng là 1.

Để minh họa thêm, bạn có thể thử phát trực tuyến boolalpha trước tiên; thì bạn sẽ thấy true thay vì 1.

+2

Chà, điều đó dạy tôi ở lại với bản in cũ tốt và nếu chỉ vì tôi hiểu nó tốt hơn. – martin

+5

@martin: Điều đó sẽ cho hành vi không xác định nếu bạn cố gắng in một con trỏ thành viên. C++ I/O ít nhất là an toàn, nếu đôi khi khó hiểu. –

+1

@martin Câu hỏi thú vị - bạn định sử dụng định dạng nào cho con trỏ tới thành viên? Bạn thậm chí không biết kích thước của sự vật (nói chung). – Angew

7
  1. Loại field là, như bạn nói, một con trỏ đến một thành viên của foo_s loại std::string.

  2. Giá trị của field1 trong tất cả các trường hợp này, bởi vì các con trỏ tới thành viên được chuyển đổi thành bool, vì vậy khi bạn xuất chúng, bạn nhận được một 1 vì họ không phải là null.

Các vấn đề liên quan