2016-11-07 4 views
7

, имеющей структуруУказатель на функцию-члена

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

я могу динамически возвращать данные членов, передавая указатель на данные членов в качестве аргумента, чтобы функционировать. например

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

и ссылающегося с использованием

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

Но мой вопрос, почему это работает? Мы передаем &Person::id базовую память, но Person является r-значением, которое идет против определения.

Я ценю все объяснения/разъяснения моего возможного непонимания темы. Спасибо.

+4

'Person' это имя типа, а не Rvalue –

+3

' & Персона :: id' внутренне представлена ​​в виде смещения в любой объект 'Person'. –

+1

«Мы передаем' & Person :: id' basicly memory »- что именно вы подразумеваете под этим? Что такое «основная память»? – AnT

ответ

6

Указатель на член в C++ можно понимать как определение «смещение». Хотя есть некоторые сложности, когда у вас есть виртуальные функции и т. Д., Но в вашем случае это достаточно хорошо.

Таким образом, в основном ваш код так же, как (если мы поворачиваем типы данных в «сырых» данных)

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

(технически говоря, приведенный выше код не компилируется, так как void * указатель не может быть использован в выражение добавления как компилятор не знает размера указателя, но давайте игнорировать это сейчас.)

и когда вы это называете, код выглядит

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

, где __offsetof является псевдооператором, который компилятор будет вычислять во время компиляции.

Вы можете видеть, что здесь нет магии. Что C++ помогает вам в том, что смещение защищено в специальном типе данных, поэтому вам не разрешается изменять его внутреннее и поэтому избегать разломов.

Дополнительная информация о C/C++ отливке указателя и арифметике

Код выше весьма основной для C/C++ пользователей, хотя это не образуют C++ профессионал хотел бы видеть (должны использовать static_cast или reinterpret_cast вместо C-типирования).

Я вижу вопрос, который задает вопрос, объясняющий дальнейшие объяснения арифметики указателей на C/C++, и это немного не по теме, поскольку это не имеет никакого отношения к вопросу, задаваемому здесь, поэтому вместо этого я даю дополнительную ссылку на эту тему.

Pointer Arithmetic

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

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

+0

спасибо за ответ, не могли бы вы объяснить return * ((int *) (p + offset)); это первый раз, когда я встретился с чем-то вроде этого. Я предположил, что это указатель на функцию, но возвращаемый тип функции указывает, что это должно быть некорректным для функции, которая возвращает poimter в int. Благодаря! – Darlyn

+1

@trolkura: Это сокращение от '* reinterpret_cast (p + offset)'. Кроме того, он используется здесь, чтобы предложить возможную реализацию. Фактические компиляторы могут работать по-разному, особенно после оптимизации. – MSalters

+1

@trolkura Кроме того, вам нужно знать, что 'int' очень отличается от' int * '. Первый тип типа «123», а более поздний - это тип указателя, указывающий на «int». –

Смежные вопросы