Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Указатель на член класса


Автор: GKosh 17.2.2006, 18:10
Вот ситуация

class CMember;

class CObject
{
CMember m_member;
};

void main()
{
CObject object();
CMember* pointer = &(object.m_member);
// pointer указывает на член класса m_member
object.m_member = CMember(); // записываем в m_member новый экземпляр

// *pointer - на что он теперь указывает?

}

Указатель на член класса действителен только пока я не инициализирую член новым экземпляром, после этого указатель указывает уже совсем не туда же, куда object.m_member.
Как же мне получить долгоживущий указатель на член класса? , чтобы и после m_member = CMember();, *pointer выдавал реальное содержание m_member?

P.S.
class CObject
{
CMember* m_member;
};
CMember** pointer = &(object.m_member);

Такой вариант не годится.

Автор: Mayk 17.2.2006, 18:23
Код

class CMember{};

struct CObject
{
     CMember m_member;
};

int main()
{
   CObject object1;
   CObject object2;

   CMember (CObject::*pointer) = &CObject::m_member;
   object1.*pointer = object2.*pointer;
}


Автор: Earnest 17.2.2006, 22:09
Цитата(GKosh @ 17.2.2006, 18:10 Найти цитируемый пост)
Указатель на член класса действителен только пока я не инициализирую член новым экземпляром, после этого указатель указывает уже совсем не туда же, куда object.m_member.

С чего бы это? Содержимое объекта, конечно, изменилось, а адрес никуда не денется, пока жив внешний объект.

Автор: MAKCim 17.2.2006, 22:23
ты же меняешь только внутреннее состояние m_member
|<><><><>||<><>...<><>||<><><>|
между | и | - память для CObject
между || и || - память для поля m_member в CObject
жирный <> это адрес первого байта m_member, который ты присваиваешь указателю
соответственно пока жив объект CObject указатель всегда указывает на верный объект, содержимое которого может меняться

Автор: GKosh 18.2.2006, 08:34
Mayk,
Интересный код, который я к сожалению пока не могу понять, если вас не затруднит, я задам еще несколько вопросов:

Почему struct CObject ? Или это не принципиально?

CMember (CObject::*pointer) = ...

Это объявление переменной? Какой тип имеет pointer?

...= &CObject::m_member

На что указывает pointer? Пока ни на что?

object1.*pointer = object2.*pointer;

Откуда в классе CObject поле pointer? Зачем вообще нужна эта строчка?

Earnest,
Возникли трудности с этим моментом, указатель на поле данных класса (если поле данных - объект) оставался действительным лишь до тех пор, пока не проходило строчки наподобии object.m_member = CMember();
Тогда я решил, что object.m_member - своего рода смещение в заголовке класса, а не указатель как можно было бы предположить, таким образом CMember* pointer = &(object.m_member) на самом деле берет всего лишь адресс экземпляра класса, в данный момент завязанного на m_member, и если этот экземпляр заменить другим, то pointer на действительное содержание m_member указывать уже не будет.

Автор: Mayk 18.2.2006, 09:33
Цитата(GKosh @ 18.2.2006, 12:34 Найти цитируемый пост)
Почему struct CObject ? Или это не принципиально?

Потому что иначе мы не может обратиться к m_member'у из main()'а. Члены класса по умолчанию закрыты, члены структуры - открыты. Попросту говоря без struct'а код не компилировался.
Цитата(GKosh @ 18.2.2006, 12:34 Найти цитируемый пост)

CMember (CObject::*pointer) = ...

Это объявление переменной?

Да.

Цитата(GKosh @ 18.2.2006, 12:34 Найти цитируемый пост)
Какой тип имеет pointer?

Это указатель на член класса. То есть то, что просилось в сабже и в окрестностях
Цитата(GKosh @ 17.2.2006, 22:10 Найти цитируемый пост)
Как же мне получить долгоживущий указатель на член класса

Долгоживущее некуда.
CObject *obj = new CObject;
obj->*pointer - суть obj->m_member
delete obj;
obj = new CObject;
obj->*pointer - опять obj->m_member, а не что-то другое

Цитата(GKosh @ 18.2.2006, 12:34 Найти цитируемый пост)
На что указывает pointer? Пока ни на что?

На m_member в CObject'е. В любом CObject'е вообще а не в каком-то конкретно.

Цитата(GKosh @ 18.2.2006, 12:34 Найти цитируемый пост)

object1.*pointer = object2.*pointer;
Откуда в классе CObject поле pointer?

Ниоткуда. pointer - это указатель на член класса, а не член класса.
object1.*pointer в данном случае это object1.m_member
(так как object1 - это object1, а pointer - это
Цитата(Mayk @ 17.2.2006, 22:23 Найти цитируемый пост)
&CObject::m_member;


Автор: GKosh 19.2.2006, 10:04
Mayk,
Хорошо, а если мне необходимо в экземпляре стороннего класса хранить указатель на поле m_member конкретного экземпляра CObject?

Автор: MAKCim 19.2.2006, 11:58
Код

template<class R, class C> struct member_ptr
{
    typedef R (C::*type); 
};

class A
{
public:
    int a;
};

class someclass
{
private:
    typedef member_ptr<int,A>::type T;
    T pointer;
public:
    someclass(T ptr): pointer(ptr) {}
};

для работы c полем a конкретного экземпляра A передпншь в свой сторонний класс (здесь someclass) указатель либо ссылку на A и используешь
Код

(ptr->*pointer)=...
(ref.*pointer)=...

Автор: LPBOY 19.2.2006, 12:13
Цитата(GKosh @ 19.2.2006, 10:04 Найти цитируемый пост)
Хорошо, а если мне необходимо в экземпляре стороннего класса хранить указатель на поле m_member конкретного экземпляра CObject?


Что значит "указатель на поле m_member конкретного экземпляра CObject"? На самом деле указатель на какое-либо поле - это просто смещение в байтах его относительно начала класса. Для всех экземпляров класса CObject это смещение будет одним и тем же.
Добавлено @ 12:17
И что за привычка у всех ставить скобки при объявлении указателя smile
Код

typedef R (C::*type);

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)