Преобразовать указатель на член в указатель на класс
От:
Аноним
Дата:
08.11.10 21:06
Оценка:
Есть объект класса С++, и я знаю указатель на один из его членов.
Как получить указатель на сам объект? Можно ли это сделать без грязных хаков, offsetof-ов, reinterpret_cast-ов и пр. ?
class Foo {
public:
Foo(): m_n(0) {}
public:
int m_n;
};
Foo* foo_member_cast(int* pi);
void main()
{
Foo foo;
int *pi=&foo.m_n;
Foo *pfoo=foo_member_cast(pi);
assert(pfoo==&foo);
}
Foo* foo_member_cast(int* pi)
{
// How to realize it?
}
Здравствуйте, Аноним, Вы писали:
А>Есть объект класса С++, и я знаю указатель на один из его членов. А>Как получить указатель на сам объект? Можно ли это сделать без грязных хаков, offsetof-ов, reinterpret_cast-ов и пр. ?
AFAIK, никак.
А в общем случае и с хаками не решается...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Преобразовать указатель на член в указатель на класс
Здравствуйте, Аноним, Вы писали:
А>Есть объект класса С++, и я знаю указатель на один из его членов. А>Как получить указатель на сам объект? Можно ли это сделать без грязных хаков, offsetof-ов, reinterpret_cast-ов и пр. ?
Без хаков — нельзя, int* не содержит никакой информации о классе. Так что только через offsetof+reinterpret_cast, но это ,сам понимаешь, хождение по граблям, потому что ты никак не сможешь проконтролировать в коде, что указатель, который к тебе пришел, указывает именно на нужный член нужного класса.
А что за задача возникла, что такое понадобилось?
Здравствуйте, jazzer, Вы писали:
А>>Есть объект класса С++, и я знаю указатель на один из его членов. А>>Как получить указатель на сам объект? Можно ли это сделать без грязных хаков, offsetof-ов, reinterpret_cast-ов и пр. ?
J>Без хаков — нельзя, int* не содержит никакой информации о классе. Так что только через offsetof+reinterpret_cast, но это ,сам понимаешь, хождение по граблям, потому что ты никак не сможешь проконтролировать в коде, что указатель, который к тебе пришел, указывает именно на нужный член нужного класса. J>А что за задача возникла, что такое понадобилось?
J>А что за задача возникла, что такое понадобилось?
Для чего это может быть нужно?
Пусть есть классы Фу и Бар, причем классу Бар для работы нужно обращаться к объекту класса Фу. Естественное решение — иметь внутри класса Бар ссылку на объект Фу:
А теперь подумаем. Зачем m_bar содержит в себе ссылку на лежащий рядом с ним m_foo?
Ведь m_bar знает указатель на себя (свой this), а компилятор знает смещение между m_foo и m_bar. То есть, m_bar может вычислить указатель на m_foo, и хранить его не нужно.
Так что, если предполагается, что Фу и Бар всегда будут использоваться в составе некой Фубар-оболочки, то, теоретически можно было бы выкинуть из Бара ссылку на Фу, заменить ее этакой compile-time ссылкой.
Отмечу также еще пару достоинств такого подхода.
У Foobar1 есть явные проблемы с копируемостью. У Foobar2 их нет.
У Bar2 и Foobar2 нет дурацких конструкторов, которые были у Bar1 и Foobar1
Re[3]: Преобразовать указатель на член в указатель на класс
Здравствуйте, Tscheineg, Вы писали:
T>Отмечу также еще пару достоинств такого подхода. T>У Foobar1 есть явные проблемы с копируемостью. У Foobar2 их нет.
А какие у Foobar1 проблемы с копируемостью?
Re[3]: Преобразовать указатель на член в указатель на класс
Здравствуйте, alpha80, Вы писали:
A>А какие у Foobar1 проблемы с копируемостью?
Класс Foobar1 содержит два члена m_foo и m_bar, причем m_bar содержит ссылку на m_foo.
А также класс Foobar1 имеет автоматически сгенерированный копирующий конструктор.
Foobar1 fbA; // fbA.m_bar содержит ссылку на fbA.m_foo
Foobar1 fbB(fbA); // fbB.m_bar содержит ссылку опять же на fbA.m_foo !!!
Хотя, логично было бы ожидать, чтобы fbB.m_bar ссылался бы на fbB.m_foo. Таким образом, автоматически сгенерированный копирующий конструктор Foobar1 нас не устраивает, значит, придется писать его вручную (или запрещать копирование)