Какова должна быть реализации функции member_shift?
Я вижу 3 варианта, но все с боками
1. Через указатель на переменную-член, который потом варварски приводится к int. Недостатки — возможные проблемы с множественным и проч. наследованием
2. Через взятия адреса переменной-члена класса через указатель на объект этого класса, равный 0. Недостаток — страшно как-то, особенно, если есть
виртуальное наследование...
3. Через инстанцирование объекта и взятие разницы адресов. Недостаток — а если нет конструктора по умолчанию или класс абстрактен?.
Здравствуйте, Went, Вы писали:
W>Возможно, уже обсуждалось, но в поиске не нашел.
W>Вопрос предельно прост: есть структура
W>Нужно определить смещение члена TestStruct::b относительно начала структуры, дабы выполнялось условие:
Здравствуйте, Сергей Мухин, Вы писали:
СМ>#ifndef FIELDOFFSET СМ>#define FIELDOFFSET(type, field) (reinterpret_cast<size_t>(&(((type *)0)->field))) СМ>#endif
Как я уже говорил, с таким вариантом не работает:
struct X
{
virtual void f() {}
int x_value;
};
struct Y : public virtual X
{
};
struct Z : public virtual X
{
};
struct W : public Z, public Y
{
int w_value;
};
void test()
{
W* w = NULL;
void* det_w = &w->w_value; //тут какая-то билебердаvoid* det_x = &w->x_value; //а тута Access violation reading location 0x00000000.
}
Возможно, я не уловил суть Вашего предложения, тогда поправьте.
Здравствуйте, Went, Вы писали:
W>Здравствуйте, Сергей Мухин, Вы писали:
СМ>>#ifndef FIELDOFFSET СМ>>#define FIELDOFFSET(type, field) (reinterpret_cast<size_t>(&(((type *)0)->field))) СМ>>#endif
W>Как я уже говорил, с таким вариантом не работает:
W>
W>struct X
W>{
W> virtual void f() {}
W> int x_value;
W>};
W>struct Y : public virtual X
W>{
W>};
W>struct Z : public virtual X
W>{
W>};
W>struct W : public Z, public Y
W>{
W> int w_value;
W>};
W>void test()
W>{
W> W* w = NULL;
W> void* det_w = &w->w_value; //тут какая-то билеберда
W> void* det_x = &w->x_value; //а тута Access violation reading location 0x00000000.
W>}
W>
W>Возможно, я не уловил суть Вашего предложения, тогда поправьте.
Здравствуйте, pavel_turbin, Вы писали:
_>должно работать _>FIELDOFFSET(W, w_value);
Это работает, видать, ошибся где-то.
А вот это:
FIELDOFFSET(W, x_value);
Не работает, ибо, по-моему, не должно работать в принципе.
Насколько я понимаю, причина тута в том, что в объекте — виртуальном наследнике класса X, по определенному смещению от начала объекта должно находиться смещение this объекта Х от начала этого объекта. То есть для того, чтобы привести экземпляр W к X нужно полезть в память, а там нас ждет билеберда, а не смещение.
Возможно, каждый компилятор сам решает как ему располагать данные объекта, но ма родном VC7.1 у меня не работает.
Здравствуйте, Went, Вы писали:
W>Здравствуйте, Анатолий Широков, Вы писали:
АШ>>То есть Вам нужен аналог offsetof? А чем сам offsetof не устраивает?
W>Наверняка, устраивает Это бустовская штука?
Нет, это ANSI-шная штука из <stddef.h>, но с виртуальным наследованием она, думаю, разобраться не сможет.
Здравствуйте, Анатолий Широков, Вы писали:
АШ>Нет, это ANSI-шная штука из <stddef.h>, но с виртуальным наследованием она, думаю, разобраться не сможет.
Здравствуйте, Went, Вы писали:
W>Здравствуйте, Анатолий Широков, Вы писали:
АШ>>Нет, это ANSI-шная штука из <stddef.h>, но с виртуальным наследованием она, думаю, разобраться не сможет.
W>Да, не разобралась
Хорошо, а если бы разобралась, то чтобы это Вам дало?
> Нужно определить смещение члена TestStruct::b относительно начала структуры, дабы выполнялось условие:
Для этого случая (POD-класс-тип), как уже упоминалось, будет работать offsetof.
> 1. Через указатель на переменную-член, который потом варварски приводится к int. Недостатки — возможные проблемы с множественным и проч. наследованием
Не возможные, а вполне реальные.
> 2. Через взятия адреса переменной-члена класса через указатель на объект этого класса, равный 0. Недостаток — страшно как-то, особенно, если есть виртуальное наследование...
В случае наличия виртуального наследования в общем случае смещение получить невозможно, т.к. оно зависит от динамического типа объекта.
#include <iostream>
struct A
{
int a;
};
struct B : virtual A
{
int b;
};
struct C : B
{
int c;
};
void ba(B& b)
{
std::cout << (char*)&b.a - (char*)&b << std::endl;
}
int main()
{
B b;
ba(b);
C c;
B& bc = c;
ba(bc);
}
VC++8:
8
12
> Подскажите пожайлуста, что лучше
Лучше рассказать, в чем заключается решаемая проблема, и, может быть, кто-нибудь сможет подсказать другое решение начальной задачи.
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Не возможные, а вполне реальные.
Да, проверил, точно реальные
ПК>В случае наличия виртуального наследования в общем случае смещение получить невозможно, т.к. оно зависит от динамического типа объекта.
Да, несоменно ты прав. Но моя задача стояла "на статике" — то есть для конкретного типа смещение конкретного члена. В случае динамики (то есть когда мне бы потребовалось взять смещение члена относительно начала имеющегося объекта) вполне подошел обычный указатель на переменную-член.
ПК>Лучше рассказать, в чем заключается решаемая проблема, и, может быть, кто-нибудь сможет подсказать другое решение начальной задачи.
Не скажу. Как я уже признавался, это скорее академический вопрос