2016-11-07 37 views
7

có cấu trúcCon trỏ trỏ tới một hàm thành viên

struct Person{ 
    Person(int i , int g):id(i),age(g){}; 
    int id; 
    int age; 
}; 

i dynamicly có thể trả lại dữ liệu thành viên bằng cách chuyển con trỏ đến dữ liệu thành viên như là đối số để hoạt động. ví dụ

int extract(Person * p , int Person::* param) 
{ 
    return p ->*param; 
} 

và gọi sử dụng

Person *p = new Person (10 , 20); 
cout << extract(p , &Person::id)<< endl; 

Nhưng câu hỏi của tôi là, tại sao không làm việc này? Chúng tôi đang chuyển &Person::id bộ nhớ cơ bản, nhưng Người là giá trị r chống lại định nghĩa.

Tôi đánh giá cao tất cả lời giải thích/làm rõ sự hiểu lầm có thể có của tôi về chủ đề. Cảm ơn.

+4

'Person' là một cái tên loại, không phải là một rvalue –

+3

'& Person :: id' được nội biểu diễn như là một bù đắp vào bất kỳ đối tượng' Person'. –

+1

"Chúng tôi đang đi qua' & Person :: id' cơ bản bộ nhớ "- chính xác những gì bạn có nghĩa là bằng cách này? "Bộ nhớ cơ bản" là gì? – AnT

Trả lời

6

Con trỏ tới thành viên trong C++ có thể được hiểu là định nghĩa "bù đắp". Mặc dù có một số biến chứng khi bạn có các chức năng ảo, nhưng trong trường hợp của bạn, điều này là đủ tốt.

Vì vậy, về cơ bản mã của bạn là giống như (nếu chúng ta biến kiểu dữ liệu để "thô" dữ liệu)

int extract(void *p, int offset) 
{ 
    return *((int*)(p+offset)); 
} 

(nói về mặt kỹ thuật, các mã trên không được biên dịch, vì một con trỏ void * không thể được sử dụng trong biểu hiện bổ sung như trình biên dịch không biết kích thước của con trỏ, nhưng chúng ta hãy bỏ qua điều này cho bây giờ.)

và khi bạn gọi nó, mã trông giống như

extract(p, __offsetof(Person, id)); 

trong đó __offsetof là một toán tử giả mà trình biên dịch sẽ tính toán nó tại thời gian biên dịch.

Bạn có thể thấy không có phép thuật ở đây. Những gì C++ giúp bạn là bù đắp được bảo vệ trong một loại dữ liệu đặc biệt, vì vậy bạn không được phép thay đổi nội bộ của nó và vì vậy tránh phá vỡ những thứ ngoài.

Thông tin thêm về C/C++ đúc con trỏ và số học

Đoạn mã trên là khá cơ bản để C/C++ sử dụng, mặc dù nó không phải là hình thức C++ chuyên nghiệp muốn nhìn thấy (phải sử dụng static_cast hay reinterpret_cast thay vì đúc C stype).

Tôi thấy người hỏi câu hỏi giải thích thêm về số học con trỏ C/C++, và đây là một chút chủ đề vì nó không liên quan gì đến câu hỏi ở đây, vì vậy thay vào đó tôi đưa ra một số tham khảo thêm về chủ đề này.

Pointer Arithmetic

http://www.technoplaza.net/programming/lesson9p2.php

http://www.informit.com/articles/article.aspx?p=686170&seqNum=8

+0

cảm ơn cho câu trả lời, bạn có nhớ giải thích trở lại * ((int *) (p + bù đắp)); đây là lần đầu tiên tôi đã gặp một cái gì đó như thế này. Tôi giả định nó là con trỏ để hoạt động nhưng kiểu trả về của hàm chỉ ra rằng nó nên là một số derreference cho hàm trả về poimter cho int. Cảm ơn! – Darlyn

+1

@trolkura: Đó là viết tắt của '* reinterpret_cast (p + offset)'. Ngoài ra, nó được sử dụng ở đây để đề xuất một triển khai có thể. Các trình biên dịch thực tế có thể hoạt động khác nhau, đặc biệt là sau khi tối ưu hóa. – MSalters

+1

@trolkura Ngoài ra, bạn cần phải biết rằng 'int' là rất khác nhau thant' int * '. Trước đây là kiểu số nguyên như '123', và sau đó là kiểu con trỏ trỏ tới' int'. –

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