Указатель на участников из мышления Брюса Экеля в C ++ - PullRequest
4 голосов
/ 05 марта 2011

Ниже приводится абзац из статьи Брюса Экеля Мышление на языке C ++ (том 1, 2-е издание, глава 11) под заголовком «Указатели на элементы»:

… указателю нужен адрес, но внутри класса «адреса» нет;Выбор члена класса означает смещение в этот класс.Вы не можете создать фактический адрес, пока не скомбинируете это смещение с начальным адресом конкретного объекта.Синтаксис указателя на член требует, чтобы вы выбирали объект одновременно с разыменованием указателя на член.

Что означает эта цитата?Я пытаюсь сделать что-то вроде:

&(objectname.member_variable)

Я получаю фактический адрес, что-то вроде 0x22f14, но это смещение означает, насколько оно далеко от начального адреса?

Ответы [ 2 ]

6 голосов
/ 05 марта 2011

Я думаю, что &(foo.bar) это просто обычный указатель на переменную.Говоря «указатель на член», мы имеем в виду что-то вроде &(FooClass::bar), без указания каких-либо объектов!Обратите внимание, что это значение может фактически вычисляться во время компиляции и может использоваться, например, в шаблонах.

Указатели-члены имеют очень странный синтаксис.

Попробуйте запустить следующий код:

#include <stdio.h>

class FooClass {
  public:
    int bar;
    int bar2;
    FooClass() : bar(0), bar2(0) {}
};

int main() {

  //Showing what member pointers actually hold:
  int FooClass::* barPtr=&FooClass::bar;
  int FooClass::* bar2Ptr=&FooClass::bar2;
  printf("barPtr=%p\nbar2Ptr=%p\n",barPtr,bar2Ptr);

  //Showing how to use them:
  FooClass foo;
  foo.*bar2Ptr=42;
  printf("foo={%d,%d}\n",foo.bar,foo.bar2);
}

Вы получите вывод:

barPtr=0x0
bar2Ptr=0x4
foo={0,42}

Как видите, оба значения содержат смещение члена от начала класса.Они могут быть вычислены, даже если вы не знаете, над каким объектом вы работаете.

Но если вы хотите разыменовать их, вы должны предоставить объект - это то, что делает оператор .*.

0 голосов
/ 05 марта 2011

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

Полученное в результате значение является позицией в памяти для элемента * member_variable *. Просто для наглядности, если вы хотите узнать смещение в байтах, вы можете сделать что-то вроде этого:

std::cout << reinterpret_cast<char *>(&(objectname.member_variable)) - reinterpret_cast<char *>(&objectname);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...