Доброго времени суток , товарищи . Кому не охота читать про нубовские проблемы , – переходите к другой теме . Не нужно унылых придирок , ибо я только учусь . Собственно , объективной критике всегда рад .
Сабж :
Методом волшебного ретурна через 2 класса передается указатель на экземпляр маленького класса , представляющего из себя пулю в комп.игре . Дальше этот адресок уходит в глобальную переменную . После этого его можно успешно использовать , но на следующей итерации цикла обработки сообщений в этом участке памяти оказывается "каша" . Члены класса приватные , и никакие методы , кроме конструкторов не занимаются их инициализацией . Проверено : конструкторы не вызываются без контрольно , указатель(глобальный) не переписывается. Я в замешательстве . Может , я чего то не учитываю при работе с указателями\ссылками ?
Код не привожу по причине обьемности .
8 октября 2009 в 15:01
Спасибо большое , объяснили доходчиво . Переделаю , с учетом всех этих деталей .
Еще раз спасибо за доходчивость , оперативность и примеры .
8 октября 2009 в 15:00
Павел, ну а мы о чём тут гутарим? О_о
8 октября 2009 в 14:00
Все, дошло… заклинило на &…
8 октября 2009 в 14:00
Либо методы должны возвращать указатель, либо testb должен быть не указателем, а экземпляром класса.
1) GBullet* GWeapon::shoot(MyPOINT wsrc , MyPOINT wdest)
{
…
return new GBullet(texbank->getTex(t) , wsrc , wdest , bullspeed , damage);
}
2) GBullet* SunPlayer::shoot(POINT mouse)
{
…
return new GBullet( bullet->shoot(pos , m) );
}
3) testb = player->shoot(mouse->getPos());
8 октября 2009 в 13:05
Это указатель (возможно, умный), т.к. используется -> а не .
Или ты о чём?…
8 октября 2009 в 13:05
Вероятно, в архитектуре т.с. этот указатель инициализируется аналогично testb
8 октября 2009 в 13:04
Да, Владимир написал тоже подходящий вариант – копирование объекта и в глобальную переменную, но объём операций в этом случае больше, чем при использовании умных указателей. Но оба варианта рабочие, и если класс небольшой – почему бы нет?
Конечно, проблема удаления объекта остаётся в обоих случаях. Боюсь, проще переделать архитектуру.
PPS. Владимир, вероятно, да (но ссылка на итерации, полагаю, не столь важна =)
8 октября 2009 в 13:04
Константин, а зачем в вашем примере
—————————
3)
static PBullet testb;
…
SunPlayer* player = …; //вот здесь создается указатель? У топостартера, очевидно, тут просто объект.
…
testb = player->shoot(mouse->getPos());
—————————
8 октября 2009 в 13:03
Пример корректного кода (псевдокод!):
typedef boost::shared_ptr<GBullet> PBullet;
1) PBullet GWeapon::shoot(MyPOINT wsrc , MyPOINT wdest)
{
…
PBullet bull = new GBullet(texbank->getTex(t) , wsrc , wdest , bullspeed , damage);
return bull;
}
2) PBullet SunPlayer::shoot(POINT mouse)
{
GWeapon bullet(…);
…
return bullet->shoot(pos , m);
}
3)
static PBullet testb;
…
SunPlayer* player = …;
…
testb = player->shoot(mouse->getPos());
Здесь есть скрытая проблема, заключающаяся в, что testb после последней инициализации будет уничтожен только при выходе из программы (но это уже вопрос твоей архитектуры – будет ли это всё корректно).
Вообще, может тебе нужен паттерн Синглтон? С возможностью замены синглтона =) Хотя, навряд-ли =)
Если что, смотри или Синглтон Майерса, или мой вариант //www.rsdn.ru/?/Frame/Main.aspx
8 октября 2009 в 13:03
Если где-то внутри итерации вы создаете локальный объект, по окончании итерации объект со всем содержимым будет удален, а память, которую занимал объект, вычищена.
Внутри итерации, судя по всему, вы создаете маленький объект GBullet bull. Этот объект – локальный, и стирается при выходе из итерации. Тот факт, что вы где-то сохранили указатель на место, где этот объект лежал, никого не волнует. Если этот объект вам нужен дальше, копируйте объект целиком (не указатель, а сам объект), или перестройте программу так, чтобы объект создавался ДО цикла (впоследствии, допустим, заполняя его нужными данными)
PS. Да, или как у Константина – память, выделенная с помощью new, чистится только с помощью delete, и никак иначе
PPS. Я правильно понял, что фрагмент 3) у топостартера более полно выглядит так:
————————————-
GBullet* testb;
….
while(…){
…
testb = &player->shoot(mouse->getPos());
…
}
————————————-
?
8 октября 2009 в 13:02
В общем случае необходимо использовать создание объекта с помощью new. И лучше использовать умный указатель – например, boost::shared_ptr. Если этого не сделать, то надо будет заботиться об удалении объекта.
А вообще, хорошо бы подумать на предмет отказа от использования глобальной переменной – нельзя ли поместить GBullet в какой-либо класс иерархии?…
8 октября 2009 в 13:01
В 1 передаётся не указатель, а сам "маленький класс" (если это С++, конечно). В 2 непонятно, что происходит (нужно указать тип bullet и раскрыть метод shoot). В 3 тоже непонятно, какой тип имеет player
Также интересно, как устроен конструктор копирования GBullet
8 октября 2009 в 13:01
Если предположить, что в 2 bullet имеет тип GWeapon, а в 3 player имеет тип SunPlayer, то возвращённый объект GBullet, во-первых, будет получен посредством конструктора копирования, во-вторых, умрёт сразу же на выходе за пределы содержащего вызов 3 блока.
Понятно объяснил?….
8 октября 2009 в 13:00
1) GBullet GWeapon::shoot(MyPOINT wsrc , MyPOINT wdest)
{
…
GBullet bull(texbank->getTex(t) , wsrc , wdest , bullspeed , damage);
return bull;
}
2) GBullet SunPlayer::shoot(POINT mouse)
{
…
return bullet->shoot(pos , m);
}
3) testb = &player->shoot(mouse->getPos());
Вот он , крестный ход адресочка памяти . testb – глобальна переменная . Разве , таким образом она пуля не продолжает жить ?
8 октября 2009 в 12:05
Ну без кода конечно трудно…
Банально: Вы уверены что ваша пуля "доживает" до следующей итерации цикла?