Russian Qt Forum
Ноябрь 05, 2024, 22:02 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Привести член к классу  (Прочитано 4613 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Октябрь 29, 2012, 16:08 »

Добрый день

Есть структурка
Код
C++ (Qt)
class CMyContext {
...
CMyPixel mPixel;
};
 
void DoSomething( CMyPixel * pix );
 
В какой-то момент внутри ф-ции DoSomething я узнаю что CPixel не какой-нибудь, а именно член класса CMyContext (исходя из др данных задачи). Как мне теперь заполучить указатель на CMyContext ?

Спасибо
Записан
Serr500
Гость
« Ответ #1 : Октябрь 29, 2012, 16:18 »

1) Поле parent в CMyPixel.
2) Какой-нибудь общий/глобальный массив вида (CMyPixel, CMyContext).
Записан
Serr500
Гость
« Ответ #2 : Октябрь 29, 2012, 16:20 »

3) А вот похитрее. Смещение mPixel в структуре известно. CMyContext можно получить как pix - offset(mPixel).
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Октябрь 29, 2012, 16:45 »

3) А вот похитрее. Смещение mPixel в структуре известно. CMyContext можно получить как pix - offset(mPixel).
Ну да, так ведь это же "С приведение" и все такое - тут же все грамотные, заклюют Улыбающийся Может есть козырный ++ способ ?
Записан
Akon
Гость
« Ответ #4 : Октябрь 29, 2012, 19:33 »

Ну вот с т.з. DoSomething зачем ей знать, что переданный объект член чего то там. Поэтому, либо передавать содержащий объкут, либо сделать двунаправленнуя связь, т.е. parent.

Цитировать
3) А вот похитрее. Смещение mPixel в структуре известно. CMyContext можно получить как pix - offset(mPixel).
Это только как временный хак.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Октябрь 29, 2012, 20:17 »

Ну вот с т.з. DoSomething зачем ей знать, что переданный объект член чего то там. Поэтому, либо передавать содержащий объкут, либо сделать двунаправленнуя связь, т.е. parent.
А кто приводил пример кросс-приведения в случае множественного наследования? Та можно сказать "рекомендовал"  Улыбающийся А тут членство вместо наследования - частая альтернатива.

Передача содержащего - явно навязанный параметр, который придется совать и совать "сверху" пока дело дойдет до DoSomething которая на самом низком уровне. Делать парента - также искусственно, что это за парент если его не назначают? Да и ничем оно не чище - после первого же копирования.

3) CMyContext можно получить как pix - offset(mPixel).
Кстати откуда взять offset и вообще как это приличнее записать?
Записан
Akon
Гость
« Ответ #6 : Октябрь 29, 2012, 23:07 »

Цитировать
А кто приводил пример кросс-приведения в случае множественного наследования? Та можно сказать "рекомендовал"   А тут членство вместо наследования - частая альтернатива.
Улыбающийся Согласен. Но там это было от своего рода безысходности. Если бы поддерживалось моком множественное да и до кучи виртуальное наследование от QObject, проблемы бы не было. У вас же руки развязаны.  

Цитировать
Передача содержащего - явно навязанный параметр, который придется совать и совать "сверху" пока дело дойдет до DoSomething которая на самом низком уровне. Делать парента - также искусственно, что это за парент если его не назначают? Да и ничем оно не чище - после первого же копирования.
Есть CMyContext и CMyPixel. Вы можете:
1. Передавать CMyContext и оставить однонапраленную связь CMyContext -> CMyPixel.
2. Передавать CMyPixel и сделать двунапраленную связь (парент) CMyContext <-> CMyPixel. Тут же получаете все проблемы двунаправленных ассоциаций. Я так понимаю, у вас классы-значения и всякие там ссылки (паренты) здесь не уместны.
3. Расширить функцию: void DoSomething(CMyContext*,  CMyPixel *); Недостаток в том, что можно подать пиксел не из того контекста. Достоинство - не нужно вводить связь между классами. Я довольно часто пользуюсь этив вариантом.

Цитировать
Кстати откуда взять offset и вообще как это приличнее записать?
Когда размер указалеля на член == sizeof(void*), то как-т так:
Код:
void DoSomething(CMyPixel *)
{
union X {
void* offset;
CMyPixel* CMyContext::* pointer;
};

X x;
x.pointer = &CMyContext::mPixel;  // далее юзайте x.offset

    ...
}
Если размер указалеля на член > sizeof(void*) (например, при виртуальном наследовании), то нужно в нем копаться и знать его формат, т.е. будут compiler-specific actions. Вообщем, не стоит хачить Улыбающийся
« Последнее редактирование: Октябрь 29, 2012, 23:53 от Akon » Записан
Serr500
Гость
« Ответ #7 : Октябрь 30, 2012, 08:04 »

Ну да, так ведь это же "С приведение" и все такое - тут же все грамотные, заклюют Улыбающийся Может есть козырный ++ способ ?
Нехай клевещут! клюют. Козырных способов я не вижу (что, впрочем, не означает, что из нет Подмигивающий )

размер указалеля на член > sizeof(void*)
Приведите примерчик.
Записан
Syveren
Гость
« Ответ #8 : Октябрь 30, 2012, 09:46 »

Цитировать
Кстати откуда взять offset и вообще как это приличнее записать?
#include  <stddef.h>
Код
C++ (Qt)
/* Offset of member MEMBER in a struct of type TYPE. */
#ifndef __cplusplus
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#else
/* The cast to "char &" below avoids problems with user-defined
   "operator &", which can appear in a POD type.  */

#define offsetof(TYPE, MEMBER)                  \
  (__offsetof__ (reinterpret_cast <size_t>          \
                 (&reinterpret_cast <const volatile char &> \
                  (static_cast<TYPE *> (0)->MEMBER))))
#endif /* C++ */

По мне так самый правильный способ передавать CMyContext. А уже внутри выуживать его элемент.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #9 : Октябрь 30, 2012, 12:05 »

Я сделал так
Код
C++ (Qt)
void DoSomething( CMyPixel * pix )
{
CMyContext * ctx = 0;
ctx = (CMyContext *)((char *) pix - (size_t) &ctx->mPixel);
printf("pix = %p, ctx = %p\n", pix, ctx);
}
 
Что по существу ничем не отличается от варианта Syveren. Делать это макросом на мой взгляд неуместно, т.к. ни к чему поощрять использование такой конструкции.

Да, возможны перекрытые операторы (char *) и/или &. Но с др стороны
Код
C++ (Qt)
#define offsetof(TYPE, MEMBER)                  \
  (__offsetof__ (reinterpret_cast <size_t>          \
                 (&reinterpret_cast <const volatile char &> \
                  (static_cast<TYPE *> (0)->MEMBER))))
#endif /* C++ */
Вот после таких конструкций выражение "монструозный язык С++" уже не кажется глупым Улыбающийся Да, это "более корректно", но это выносит мозг программиста заставляя вникать в дебри витиеватого синтаксиса.

Akon, попытки сделать это "просто корректным" введя доп поля (связи) разбиваются просто
Код
C++ (Qt)
CMyPixel::CMyPixel( const CMyPixel & )
{
//.. ???
}
 
Выясняется что CMyPixel не может решить что же с парентом, в результате каждое присвоение потребует внимания - такое лекарство хуже болезни
« Последнее редактирование: Октябрь 30, 2012, 12:07 от Igors » Записан
Akon
Гость
« Ответ #10 : Октябрь 31, 2012, 21:13 »

Цитировать
static_cast<TYPE *> (0)->MEMBER
А до этого я сходу не допер Улыбающийся

Цитировать
Akon, попытки сделать это "просто корректным" введя доп поля (связи) разбиваются просто
Код
C++ (Qt)
CMyPixel::CMyPixel( const CMyPixel & )
{
//.. Непонимающий
}
 
Выясняется что CMyPixel не может решить что же с парентом, в результате каждое присвоение потребует внимания - такое лекарство хуже болезни
Да, разумеется это большой напряг. Этот вариант, как правило, применяется для классов-сущностей (а они, как правило, с Q_DISABLE_COPY)
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.407 секунд. Запросов: 23.