Среда, 18 Декабря 2024, 17:30

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 1
  • 1
Проблема с производным классом
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
почетный гость
Сейчас нет на сайте
Ну а как нормально получить указатель на объект производного класса, имея указатель только на его базовую часть...?
Возможно у меня не правильна сама архитектура игрового цикла, если возникаю такие проблемы?)))
И самое интересное что нигде подобной информации не найдешь, а все молчат, как будто это вселенская тайна wink
Нет что бы какой то хороший человек сказал: "Я делаю так и так..."

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 всёравно не катит tongue ...
Хотя он может её переписать...



Я: О великий повелитель этой ничтожной вселенной - сокращённо ЁЖ!
FaetonДата: Пятница, 05 Ноября 2010, 13:16 | Сообщение # 19
частый гость
Сейчас нет на сайте
))))))))))) А я между прочим писал:
В случае если объявленный указатель на некоторый класс, ссылается на объект дочернего класса, доступ к его методу можно получить лишь таким способом

в другом посте ниже
альтернатива приведению указателей так называемое "позднее связывание методов" посредством virtual

ещё ниже
Вообще то доступ к переменным грамотно делать посредством методов. А все поля должны быть private или protected. И тогда в силу всупает необходимость virtual методов в родительском классе.
Это называется хорошим стилем. В результате легко манипулировать сложными классами образуемые наследованием. Поэтому и смог закончить сложные проекты)))

Вот вам)))))))) Короче дал понять в последнем посте, что реализовать можно грамотней и показал с помощью чего)))

RenusДата: Пятница, 05 Ноября 2010, 16:09 | Сообщение # 20
почетный гость
Сейчас нет на сайте
Ну для этого проекта оставим так, он все таки первый...
А вообще virtual у меня используется очень даже сильно, собсно у каждого объекта есть функции Process и Render которые виртуальные и у имеют свою реализацию для каждого класса...
  • Страница 1 из 1
  • 1
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг