Где хранятся функции-члены для объекта?

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

Я не понимаю, почему, даже если у меня могут быть указатели на функции-члены, следующий код не работает:

struct mystruct
{
void function()
{
cout << "hello world";
}
int c;
};

int main()
{
unsigned int offset_from_start_structure = (unsigned int)(&((mystruct*)0)->c);
unsigned int offset_from_start_structure2 = (unsigned int)(&((mystruct*)0)->function); // ERROR - error C2276: '&' : illegal operation on bound member function expressionreturn 0;
}

Мой вопрос: почему линия

unsigned int offset_from_start_structure = (unsigned int)(&((mystruct*)0)->c);

компилирует и возвращает мне смещение поля «c» от начала структуры и строки

unsigned int offset_from_start_structure2 = (unsigned int)(&((mystruct*)0)->function);

даже не компилируется?

8

Решение

Функции-члены или указатели на них не хранятся в объекте. (virtual функции обычно вызываются с помощью указателя, хранящегося в таблице, на которую объект имеет единственный указатель) огромный трата памяти. Обычно они хранятся в разделе памяти кода и известны компилятору. Предмет (*this) обычно передается как невидимый параметр, чтобы функции знали, с каким объектом работать при их вызове.

Итак, с точки зрения непрофессионала, вы бы имели

 0x10001000    void A::foo
..........    {code for A::foo}

а также

 push a;
call A::foo (0x10001000)
pop a;

где a это объект, который вы называете foo на.

16

Другие решения

Указатели на функции-члены на практике не хранятся в объектах: в этом нет необходимости. Стандарт C ++ не определяет, как именно, например, виртуальные функции должны быть реализованы, но обычная практика для виртуальных функций-членов состоит в том, что каждый объект содержит указатель на таблицу указателей функций; этот указатель называется указатель vtable.

Вы можете попытаться заполучить «Внутри объектной модели C ++» Стэнли Липпман.

Или вы можете просто попытаться достать мой старый руководство по указателям, на которую когда-то ссылались из статьи-указателя Википедии, до того, как исчез мой тогдашний сайт.


Что касается второго вопроса, зачем брать адрес p->memberFunc делает компилятор немного подавленным, хорошо, что выражение не имеет типа, это просто синтаксическая сущность, к которому вы можете применить список аргументов для вызова функции.

Для остроумия,

struct S
{
void foo() {}
};

#include <iostream>
#include <typeinfo>
using namespace std;
int main()
{
S* p = 0;
typeid( &p->foo );
}

Компиляция:

[W: \ DEV \ тест]
> g ++ foo.cpp
foo.cpp: в функции 'int main ()':
foo.cpp: 12: 17: ошибка: ISO C ++ запрещает принимать адрес связанной функции-члена для формирования указателя на функцию-член. Скажите 'S :: foo' [-fpermissive]
foo.cpp: 12: 22: предупреждение: вычисленное значение не используется [-Wunused-value]
foo.cpp: 12: 22: предупреждение: инструкция не действует [-Wunused-value]

[W: \ DEV \ тест]
> _
2

По вопросам рекламы [email protected]