| Проблема с производным классом | 
|  | 
| 
| Renus | Дата: Среда, 03 Ноября 2010, 11:22 | Сообщение # 1 |  |   почетный гость Сейчас нет на сайте | Всем привет. Щас спрошу вопрос, может я совсем туплю конечно, но что то с утра не додумывается...
  Есть список в который занесены все объекты, список хранит указатели на переменные собственного типа CObject, CObject в свою очередь базовый класс для всех объектов остальных игровых классов(CPlayer, CBullet и т.д.) Собсно вопрос в том как вытянуть значение внутренней переменной производного класса, пули например.
 Вот небольшой код для попадания пули по врагу:
 
 Code  CrossIter=Obj_List.begin();
 CObject* pObject;
 while(CrossIter!=Obj_List.end())
 {
 pObject=*CrossIter;
 if (pObject->type=="bullet")
 {
 if (CheckColl(cbox, pObject->cbox)==true)
 {
 armor-=pObject->damage; // Вот тут надо получить доступ как к CBullet, а не CObject
 pObject->kill=true;
 }
 }
 CrossIter++;
 }
 Извините за кривую формулировку вопроса... |  |  |  |  | 
| 
| ezhickovich | Дата: Среда, 03 Ноября 2010, 12:36 | Сообщение # 2 |  |   [Великий и могучий хозяинъ] Сейчас нет на сайте | Renus, тоесть если говорить проще, то ты хочешь получить доступ к элементам не определённым в базовом классе? Ты не можешь работать с ними т.к. компилятор не знает о их существовании... (как и о всех других неопределённых элементах)
 Но без выходных ситуаций не бывает...
  К примеру... (не самый удачный пример... хотя...) Можно реализовать функцию которая по имени параметра вернёт указатель на void...
 Вот так:
  virtual void* getParam (const char *name) = 0; // Для базового класса   И:   virtual void* getParam (const char *name) // Для дочернего класса {
 if (strstr (name, "damage") != NULL) return (void*)&damage;
 return NULL;
 }
  А использовать так: int d = *(int*)(obj->getParam("damage"));
  Вот примерно так... 
 
   Я: О великий повелитель этой ничтожной вселенной - сокращённо ЁЖ!
 
 
 Сообщение отредактировал ezhickovich - Среда, 03 Ноября 2010, 12:47 |  |  |  |  | 
| 
| Renus | Дата: Среда, 03 Ноября 2010, 16:41 | Сообщение # 3 |  |   почетный гость Сейчас нет на сайте | В таком случае будет легче вынести все параметры объектов куда нибудь, и получать их через параметр базового класса. К примеру дать базовому классу переменную type, и определять ее в конструкторе при создании объектов, а через функции получать доступ к всяким параметрам...
 Опять навалил непонятно чего)))
 Интересно просто как люди делают, неужели нет более изящного подхода...?
 Добавлено (03.11.2010, 16:41)---------------------------------------------
 Можно еще правда разделить списки, сделать отдельно для всех типов объектов и обрабатывать их по очереди, тогда будет не посредственный доступ ко всем параметрам производных классов...
  Жду предложений))) |  |  |  |  | 
| 
| ezhickovich | Дата: Среда, 03 Ноября 2010, 16:53 | Сообщение # 4 |  |   [Великий и могучий хозяинъ] Сейчас нет на сайте | Renus, Ты предлагаешь в базовом классе определить все параметры дочерних классов, а в дочерних классах просто изменить уровень доступа к ним? Всё бы и хорошо если бы это исключало вероятность случайного использования закрытых переменных...
 Т.к. все переменные уже будут определены в родительском классе, то компилятор скушает сию мерзость как так и надо, но во время работы приложения есть очень большая вероятность наткнуться на ошибку доступа к памяти по адресу...
 Да и вообще этот подход сам по себе карявый...
   Quote (Renus) Можно еще правда разделить списки, сделать отдельно для всех типов объектов и обрабатывать их по очереди, тогда будет не посредственный доступ ко всем параметрам производных классов...Можно, но это лишняя работа как программиста, так и машины...
 А время=деньги...
 
 
   Я: О великий повелитель этой ничтожной вселенной - сокращённо ЁЖ!
 |  |  |  |  | 
| 
| Renus | Дата: Четверг, 04 Ноября 2010, 19:24 | Сообщение # 5 |  |   почетный гость Сейчас нет на сайте | Ну а как нормально получить указатель на объект производного класса, имея указатель только на его базовую часть...? Возможно у меня не правильна сама архитектура игрового цикла, если возникаю такие проблемы?)))
 И самое интересное что нигде подобной информации не найдешь, а все молчат, как будто это вселенская тайна
   Нет что бы какой то хороший человек сказал: "Я делаю так и так..."
  P. S. Пожалуйста, прошу всех игроделов-программистов, расскажите как вы храните игровые объекты и осуществляете взаимодействия между ними!!! Добавлено (04.11.2010, 19:24)---------------------------------------------
 Ну вот, и все молчат...
 |  |  |  |  | 
| 
| ezhickovich | Дата: Четверг, 04 Ноября 2010, 19:52 | Сообщение # 6 |  |   [Великий и могучий хозяинъ] Сейчас нет на сайте | Нуу... Я уже высказал свои идеи... 
 
   Я: О великий повелитель этой ничтожной вселенной - сокращённо ЁЖ!
 |  |  |  |  | 
| 
| Faeton | Дата: Четверг, 04 Ноября 2010, 20:24 | Сообщение # 7 |  |   частый гость Сейчас нет на сайте | Добрый вечер. Необходимо привести к типу CBullet* armor-=( CBullet*)pObject->damage;
 |  |  |  |  | 
| 
| ezhickovich | Дата: Четверг, 04 Ноября 2010, 21:25 | Сообщение # 8 |  |   [Великий и могучий хозяинъ] Сейчас нет на сайте | Мда, это уже точно получше того, что предлагал я =) Добавлено (04.11.2010, 21:25)---------------------------------------------
 Хотя... Всё хорошо к месту...
 Поставлю плюс в репу...
 
 
   Я: О великий повелитель этой ничтожной вселенной - сокращённо ЁЖ!
 |  |  |  |  | 
| 
| Renus | Дата: Пятница, 05 Ноября 2010, 01:27 | Сообщение # 9 |  |   почетный гость Сейчас нет на сайте | Да не хочет, выдает ошибку, пишет что damage не является членом "CObject" По моему с указателями так нельзя...
 Добавлено (05.11.2010, 01:27)---------------------------------------------
 Если решать вопрос таким способом, то нужно каким либо способом привести указатель к типу CBullet*, или получить его где нибудь...
 Ну, что то моих познаний тут не хватает(((
 |  |  |  |  | 
| 
| Faeton | Дата: Пятница, 05 Ноября 2010, 09:22 | Сообщение # 10 |  |   частый гость Сейчас нет на сайте | Да не хочет, выдает ошибку, пишет что damage не является членом "CObject" Это уже из области фантастики.
 То что я предложил стандартное приведение типа указателя. В случае если объявленный указатель на некоторый класс, ссылается на объект дочернего класса, доступ к его методу можно получить лишь таким способом. Если же всё таки ругается компилятор значит ошибка в другом месте. Например в списке действительно хранятся указатели на объекты дочерних классов (разумеется при этом список объявлен как список указателей родительского класса)
 Добавлено (05.11.2010, 09:22)---------------------------------------------
 так должен выглядеть код:
 CrossIter=Obj_List.begin();
 CObject* pObject;
 CBullet *pBullet;
 while(CrossIter!=Obj_List.end())
 {
 pObject=*CrossIter;
 if (pObject->type=="bullet")
 {
 if (CheckColl(cbox, pObject->cbox)==true)
 {
 pBullet=( CBullet*)pObject; //то же самое что я писал раньше только чуть более развёрнуто
 armor-=pBullet->damage; // Вот тут надо получаем доступ как к CBullet, а не CObject
 pObject->kill=true;
 }
 }
 CrossIter++;
 }
 |  |  |  |  | 
| 
| ezhickovich | Дата: Пятница, 05 Ноября 2010, 09:28 | Сообщение # 11 |  |   [Великий и могучий хозяинъ] Сейчас нет на сайте | Нужно поставить ещё одни скобки... Иначе получается, что приводим неопределённую переменную damage к типу CBullet* - FAIL
 Чуть исправил:
 
 Code #include <cstdio> 
 class A {};
 class B : public A
 {
 public: int foo;
 };
 
 int main ()
 {
 A *a = new B;
 ((B*)a)->foo = 10;
 int foo = ((B*)a)->foo;
 printf ("%d", foo);
 return 0;
 }
На экран должно быть выведено "10"
 
 
   Я: О великий повелитель этой ничтожной вселенной - сокращённо ЁЖ!
 |  |  |  |  | 
| 
| Faeton | Дата: Пятница, 05 Ноября 2010, 10:48 | Сообщение # 12 |  |   частый гость Сейчас нет на сайте | скобки не проверял)))(просто скопировал код и вставил свои строки) Целью видел показать пример использования механизма приведения типов указателей |  |  |  |  | 
| 
| ezhickovich | Дата: Пятница, 05 Ноября 2010, 10:53 | Сообщение # 13 |  |   [Великий и могучий хозяинъ] Сейчас нет на сайте | Quote (Faeton) armor-=( CBullet*)pObject->damage;Просто этот код не может компилиться =)
 А если поставить всего две скобки, то всё ок...
 P.S. Откуда код взял?
 
 
   Я: О великий повелитель этой ничтожной вселенной - сокращённо ЁЖ!
 |  |  |  |  | 
| 
| Faeton | Дата: Пятница, 05 Ноября 2010, 11:12 | Сообщение # 14 |  |   частый гость Сейчас нет на сайте | Понял))))действительно, забыл скобки. Внутренние скобки нужны для указания в какой тип привести, а внешние указывают, что привести. код Renus, я просто вставил свои строки, для наглядности.
 А вообще
 armor-=(( CBullet*)pObject)->damage;// даёт доступ к свойству CBullet в данный "момент" кода
 Добавлено (05.11.2010, 11:12)---------------------------------------------
 альтернатива приведению указателей так называемое "позднее связывание методов" посредством virtual
 |  |  |  |  | 
| 
| ezhickovich | Дата: Пятница, 05 Ноября 2010, 11:25 | Сообщение # 15 |  |   [Великий и могучий хозяинъ] Сейчас нет на сайте | В данном случае мы имеем дело с переменной => virtual не катит... 
 
   Я: О великий повелитель этой ничтожной вселенной - сокращённо ЁЖ!
 |  |  |  |  | 
| 
| Renus | Дата: Пятница, 05 Ноября 2010, 11:35 | Сообщение # 16 |  |   почетный гость Сейчас нет на сайте | О! Заработало!!!! Спасибо ребят, даю плюс в репы)))
 НА выходных постараюсь выложить новую версию своей игрушки, а через недельку возможно версию для тестов, так заходите и смотрите)
 |  |  |  |  | 
| 
| Faeton | Дата: Пятница, 05 Ноября 2010, 12:24 | Сообщение # 17 |  |   частый гость Сейчас нет на сайте | В данном случае мы имеем дело с переменной => virtual не катит... Вообще то доступ к переменным грамотно делать посредством методов. А все поля должны быть private или protected. И тогда в силу всупает необходимость virtual методов в родительском классе.
 Это называется хорошим стилем. В результате легко манипулировать сложными классами образуемые наследованием. Поэтому и смог закончить сложные проекты)))
 |  |  |  |  | 
| 
| ezhickovich | Дата: Пятница, 05 Ноября 2010, 12:45 | Сообщение # 18 |  |   [Великий и могучий хозяинъ] Сейчас нет на сайте | Тем не менее у автора не такая реализация... => virtual всёравно не катит  ... Хотя он может её переписать...
 
 
   Я: О великий повелитель этой ничтожной вселенной - сокращённо ЁЖ!
 |  |  |  |  | 
| 
| Faeton | Дата: Пятница, 05 Ноября 2010, 13:16 | Сообщение # 19 |  |   частый гость Сейчас нет на сайте | ))))))))))) А я между прочим писал: В случае если объявленный указатель на некоторый класс, ссылается на объект дочернего класса, доступ к его методу можно получить лишь таким способом
  в другом посте ниже альтернатива приведению указателей так называемое "позднее связывание методов" посредством virtual
  ещё ниже Вообще то доступ к переменным грамотно делать посредством методов. А все поля должны быть private или protected. И тогда в силу всупает необходимость virtual методов в родительском классе.
 Это называется хорошим стилем. В результате легко манипулировать сложными классами образуемые наследованием. Поэтому и смог закончить сложные проекты)))
  Вот вам)))))))) Короче дал понять в последнем посте, что реализовать можно грамотней и показал с помощью чего))) |  |  |  |  | 
| 
| Renus | Дата: Пятница, 05 Ноября 2010, 16:09 | Сообщение # 20 |  |   почетный гость Сейчас нет на сайте | Ну для этого проекта оставим так, он все таки первый... А вообще virtual у меня используется очень даже сильно, собсно у каждого объекта есть функции Process и Render которые виртуальные и у имеют свою реализацию для каждого класса...
 |  |  |  |  |