HLFX.Ru Forum
профиль •  правила •  регистрация •  календарь •  народ •  FAQ •  поиск •  новое •  сутки •  главная •  выход  
HLFX.Ru Forum HLFX.Ru Forum > Наш форум > Технические вопросы > [CPP] this << F1 // OOP: субклассы в массивах
уже полгода я не программирую. толстый стал как пельмень...
  Предыдущая тема   Следующая тема
Автор
Тема Новая тема    Ответить
~ X ~
offline

Дата регистрации: Oct 2005
Проживает: Архангельск
Сообщений: 3619

Рейтинг



Награды
 
[1 награда]


Red face [CPP] this << F1 // OOP: субклассы в массивах

Под воздействием потенциальных пользователей пытался на днях дописать аврора-совместимую партикакал-систем. И тут ВНЕЗАПНО я задался вопросом...

Вот такие партиклы:

C++ Source Code:
1
class CParticle
2
{
3
public:
4
  CParticle();
5
  virtual ~CParticle();
6
 
7
  bool IsFree(void);
8
  virtual void Render(const Vector &rt, const Vector &up, const int &rendermode, const bool &doubleside = false);
9
 
10
  ...
11
 
12
  Vector m_vPos;// current position
13
  Vector m_vPosPrev;// previous position
14
  Vector m_vVel;// velocity
15
  Vector m_vAccel;// acceleration (gravity, etc.)
16
 
17
  float m_fEnergy;// should change from 1 to 0 during particle lifetime (linear)  // do we really need this?
18
  float m_fSizeX;// particle size in world units
19
  float m_fSizeY;
20
  float m_fSizeDelta;
21
  float m_fColor[4];// color in RGBA (0...1) format
22
  float m_fColorDelta[4];
23
 
24
  unsigned int m_iFlags;
25
  int m_iFrame;
26
  int index;// index in my system, assigned in AllocateParticle()
27
 
28
//protected:
29
  model_t *m_pTexture;
30
};
31
 
32
 
33
// Что здесь важно - так это добавленеи новых свойств, занимающих немало места...
34
class CParticleAur : public CParticle
35
{
36
public:
37
  CParticleAur();
38
  virtual void Render(const Vector &rt, const Vector &up, const int &rendermode, const bool &doubleside = false);
39
 
40
  CParticleAur	*m_pOverlay;// for making multi-layered CParticles
41
  CParticleType	*m_pType;// a pointer to its type
42
  Vector		m_vecWind;
43
  float		m_fAngle;
44
  float		m_fAngleDelta;
45
  float		m_fFrameDelta;
46
  float		m_fDrag;
47
  float		age;
48
  float		age_death;
49
  float		age_spray;
50
};
51
 


Разница, какгрится, видна невооружённым тазом.
Хранятся они вот так:

C++ Source Code:
CParticle *m_pParticleList;


Создаются так:
C++ Source Code:
m_pParticleList = new CParticleAur[m_iMaxParticles];// allocate custom class


...а кагже правильно это всё обрабатывать? Моё программерское чутьё подсказывает, что вот это будет плохо:

C++ Source Code:
1
void CPSAurora::Render(void)
2
{
3
  //	if (PointIsVisible(m_vecOrigin))
4
  {
5
    //		CPSAurora::BaseClass::Render();
6
    Vector v_up, v_right;
7
    AngleVectors(g_vecViewAngles, NULL, v_right, v_up);
8
    CParticleAur *p = NULL;
9
    for (uint32 i = 0; i < m_iMaxParticles; ++i)// XDM3037: unstable m_iNumParticles; ++i)
10
    {
11
      p = (CParticleAur *)&m_pParticleList[i];
12
      if (p->m_fEnergy <= 0.0f || p->m_fSizeX <= 0.0f)
13
        continue;
14
 
15
      ...
16
    }


...потому что m_pParticleList[i] нихрена не знает про CParticleAur и отсчитывает элементы в виде CParticle. Т.е. вот это должно работать:

C++ Source Code:
1
CParticleAur *p = NULL;
2
CParticleAur *m_pParticleList = (CParticleAur *)m_pParticleList;
3
for (uint32 i = 0; i < m_iMaxParticles; ++i)// XDM3037: unstable m_iNumParticles; ++i)
4
{
5
  p = (CParticleAur *)&pParticleList[i];


...так?

__________________
Минутка полезного:
Бесплатный UT-подобный Half-Life mod.
Бесплатный редактор для 32-битных текстур. Без дотнета.
Бесплатный IDE для любых компиляторов и ЯП.
Бесплатная Windows-подобная ОС.
Проверка грамматики русского языка.
Чат по hl[fx]: [email protected]

Сообщить модератору | | IP: Записан
Сообщение: 140335

Старое сообщение 27-08-2014 08:42
- За что?
marikcool
Житель форума

Дата регистрации: Jul 2011
Проживает: kz
Сообщений: 1522
Возраст: 37

Рейтинг



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

__________________
vk.com/skullcapstudios

Сообщить модератору | | IP: Записан
Сообщение: 140345

Старое сообщение 27-08-2014 13:21
- За что?
 XaeroX
Crystice Softworks

Дата регистрации: Oct 2005
Проживает: Торонто
Сообщений: 34523
Нанёс повреждений: 514 ед.
Возраст: 37

Рейтинг



Награды
 
[1 награда]


Цитата:
~ X ~ писал:
...так?

Да, так вполне должно работать.
Другой вопрос - а зачем ты заводил массив типа CParticle, а не CParticleAur?
Он где-то обходится в родительском классе? Тогда ты получишь ошибку в нём, из-за того, что он будет обходиться как массив CParticle с совершенно другим размером элемента.

__________________

Сообщить модератору | | IP: Записан
Сообщение: 140346

Старое сообщение 27-08-2014 13:23
-
marikcool
Житель форума

Дата регистрации: Jul 2011
Проживает: kz
Сообщений: 1522
Возраст: 37

Рейтинг



А не все верно, последовательность наследования перепутал. За указатель массива не парься, можешь хоть просто войд написать.

__________________
vk.com/skullcapstudios

Сообщить модератору | | IP: Записан
Сообщение: 140347

Старое сообщение 27-08-2014 13:24
- За что?
 XaeroX
Crystice Softworks

Дата регистрации: Oct 2005
Проживает: Торонто
Сообщений: 34523
Нанёс повреждений: 514 ед.
Возраст: 37

Рейтинг



Награды
 
[1 награда]


Цитата:
marikcool писал:
А на последнем получишь скорее всего краш

С чего бы?

__________________

Сообщить модератору | | IP: Записан
Сообщение: 140348

Старое сообщение 27-08-2014 13:25
-
marikcool
Житель форума

Дата регистрации: Jul 2011
Проживает: kz
Сообщений: 1522
Возраст: 37

Рейтинг



Цитата:
XaeroX писал:

Перепутал

__________________
vk.com/skullcapstudios

Сообщить модератору | | IP: Записан
Сообщение: 140349

Старое сообщение 27-08-2014 13:27
- За что?
~ X ~
offline

Дата регистрации: Oct 2005
Проживает: Архангельск
Сообщений: 3619

Рейтинг



Награды
 
[1 награда]


XaeroX почему же? Краш получен. Прям таки клубничный. Потому что CParticle намного меньше CParticleAur.
Проблема в том, что аллокатор и хранилище - внутри CParticleSystem - базового класса всех ПС (их много, очень много). И тащить свойства CParticleAur внутрь CParticle - это нарываться на падение производительности и перерасход памяти.

Вощем, я и сам подумывал над массивом указателей, но уж очень не хочется переписывать методы обращения в... 9 системах. :-/ По нескольку в каждой. Потом отлаживать, искать опечатки... Или накручивать абстракцию типа GetParticle(i), получая по распухшему стеку...

__________________
Минутка полезного:
Бесплатный UT-подобный Half-Life mod.
Бесплатный редактор для 32-битных текстур. Без дотнета.
Бесплатный IDE для любых компиляторов и ЯП.
Бесплатная Windows-подобная ОС.
Проверка грамматики русского языка.
Чат по hl[fx]: [email protected]

Сообщить модератору | | IP: Записан
Сообщение: 140351

Старое сообщение 27-08-2014 13:49
- За что?
 XaeroX
Crystice Softworks

Дата регистрации: Oct 2005
Проживает: Торонто
Сообщений: 34523
Нанёс повреждений: 514 ед.
Возраст: 37

Рейтинг



Награды
 
[1 награда]


Цитата:
~ X ~ писал:
почему же? Краш получен. Прям таки клубничный.

В той ситуации, что ты описал в 1 посте, краш невозможен с точки зрения банальной эрудиции.

__________________

Сообщить модератору | | IP: Записан
Сообщение: 140356

Старое сообщение 27-08-2014 17:31
-
FreeSlave
Житель форума

Дата регистрации: Nov 2007
Проживает: Тула
Сообщений: 1077

Рейтинг



XaeroX, краш как раз очень даже возможен везде кроме первого элемента массива (по ясным причинам).
При таком преобразовании выкладка массива (обращение по элементам) становится невалидной. А так как указатель на таблицу виртуальных функций являются частью объекта, при таком раскладе происходит обращение по "мусорному" адресу и попытка найти там адрес нужной функции и выполнить её код.

Минимизрованный пример:

C++ Source Code:
1
#include <iostream>
2
 
3
class Base
4
{
5
public:
6
  virtual void say()
7
  {
8
    std::cout << "Base" << std::endl;
9
  }
10
  int i; //some payload
11
};
12
 
13
class Derived : public Base
14
{
15
public:
16
  virtual void say()
17
  {
18
    std::cout << "Derived" << std::endl;
19
  }
20
  int j; //some payload
21
};
22
 
23
int main()
24
{
25
  Derived* derives = new Derived[4];
26
  Base* bases = derives;
27
  std::cout << sizeof(Base) << std::endl;
28
  std::cout << sizeof(Derived) << std::endl;
29
  std::cout << &derives[1] << ' ' << &bases[1] << std::endl;
30
  bases[1].say();
31
  return 0;
32
}


Решение: как уже говорилось, использовать массив указателей вместо массива значений.

Цитата:
~ X ~ писал:
не хочется переписывать методы обращения


Ты имеешь в виду различие между . и -> ?

Сообщить модератору | | IP: Записан
Сообщение: 140357

Старое сообщение 27-08-2014 18:27
- За что?
 XaeroX
Crystice Softworks

Дата регистрации: Oct 2005
Проживает: Торонто
Сообщений: 34523
Нанёс повреждений: 514 ед.
Возраст: 37

Рейтинг



Награды
 
[1 награда]


Народ, ну вы что... Сегодня же вроде не пятница...

Цитата:
~ X ~ писал:
C++ Source Code:
1
CParticle *m_pParticleList = new CParticleAur[m_iMaxParticles];// allocate custom class
2
...
3
CParticleAur *p = NULL;
4
CParticleAur *m_pParticleList = (CParticleAur *)m_pParticleList;
5
for (uint32 i = 0; i < m_iMaxParticles; ++i)// XDM3037: unstable m_iNumParticles; ++i)
6
{
7
  p = (CParticleAur *)&pParticleList[i];

Где в этом коде вылет будет, ткните мне пальцем.
Именно этот код привёл автор поста.

__________________

Сообщить модератору | | IP: Записан
Сообщение: 140359

Старое сообщение 27-08-2014 18:42
-
FreeSlave
Житель форума

Дата регистрации: Nov 2007
Проживает: Тула
Сообщений: 1077

Рейтинг



Цитата:
XaeroX писал:
Где в этом коде вылет будет, ткните мне пальцем.

А, ты об этом Ну если там всегда будут CParticleAur, пусть и под видом CParticle, то да. Только вот зачем тогда эти преобразования туда-сюда.

Сообщить модератору | | IP: Записан
Сообщение: 140361

Старое сообщение 27-08-2014 18:46
- За что?
 XaeroX
Crystice Softworks

Дата регистрации: Oct 2005
Проживает: Торонто
Сообщений: 34523
Нанёс повреждений: 514 ед.
Возраст: 37

Рейтинг



Награды
 
[1 награда]


Цитата:
FreeSlave писал:
А, ты об этом

Ну, как бы да.

__________________

Сообщить модератору | | IP: Записан
Сообщение: 140362

Старое сообщение 27-08-2014 18:47
-
~ X ~
offline

Дата регистрации: Oct 2005
Проживает: Архангельск
Сообщений: 3619

Рейтинг



Награды
 
[1 награда]


XaeroX ты привёл мой "рабочий" пример. Прочти ещё раз текст вокруг вставок. Первый пример - краш, второй - работает.

забыл скопипастить:

C++ Source Code:
1
class CPSAurora : public CParticleSystem
2
{
3
  typedef CParticleSystem BaseClass;
4
public:
5
  CPSAurora(void);
6
  CPSAurora(const char *filename, int attachment);
7
  virtual ~CPSAurora(void);
8
  ...
9
}
10
 
11
 
12
class CParticleSystem : public CRenderSystem
13
{
14
  typedef CRenderSystem BaseClass;
15
public:
16
  ...
17
protected:
18
  ...
19
  CParticle *m_pParticleList;
20
};
21
}


Вобщем, похоже, что да, придётся делать массив указателей т.к. внутри базовой CParticleSystem идёт иногда итерация партиклов по типу CParticle.

Грёбаная аврора, как же я её ненавижу!!

__________________
Минутка полезного:
Бесплатный UT-подобный Half-Life mod.
Бесплатный редактор для 32-битных текстур. Без дотнета.
Бесплатный IDE для любых компиляторов и ЯП.
Бесплатная Windows-подобная ОС.
Проверка грамматики русского языка.
Чат по hl[fx]: [email protected]

Сообщить модератору | | IP: Записан
Сообщение: 140367

Старое сообщение 28-08-2014 07:06
- За что?
ComradeAndrew
Житель форума

Дата регистрации: Aug 2014
Проживает: Дубай
Сообщений: 510
Возраст: 27

Рейтинг



~ X ~:
Я так понимаю ты хочешь обойти краш, который возникает из-за обращения к CParticle []?
Можешь использовать функцию для получения элемента массива

C++ Source Code:
1
CParticle* getCParticle(CParticle* particleList, int stride, int id)
2
{
3
  return (CParticle*)((char*)particleList + stride*id);
4
}
5
 
6
...
7
 
8
//что-то вроде
9
CParticle *p = getCParticle(m_pParticleList, siszeof(CParticleAur), 1);


Ну или перегрузить оператор [] для CParticle по аналогии. Должно работать. Если тебе не хочется переписывать под массив указателей. Но вряд ли это можно назвать лучшем способом (:

P.S. XaeroX прав: краша в том коде, который ты показывал быть не могло.

Сообщить модератору | | IP: Записан
Сообщение: 140371

Старое сообщение 28-08-2014 10:28
- За что?
~ X ~
offline

Дата регистрации: Oct 2005
Проживает: Архангельск
Сообщений: 3619

Рейтинг



Награды
 
[1 награда]


ComradeAndrew я об этом уже говорил. Про гетпартикл. Но это уже ужос какой-то. А STL использовать ну никак не хочется.
Вобщем, думаю.
Наверное, всё-таки, придётся писать обёртку типа:

C++ Source Code:
1
// Creation 1:
2
fot (i=0;i<n;++i)
3
m_pParticleList[i] = new CWhateverParticle;// non-contiguous segments: BAD
4
 
5
// Creation 2:
6
CWhateverParticle *pContainer = new CWhateverParticle[n];// contiguous array
7
fot (i=0;i<n;++i)
8
m_pParticleList[i] = &pContainer[i];
9
 
10
// Usage:
11
m_pParticleList[i]->KillSomePigeons();
12
 
13
// Destruction 1:
14
fot (i=0;i<n;++i)
15
delete m_pParticleList[i];
16
 
17
// Destruction 2:
18
fot (i=0;i<n;++i)
19
m_pParticleList[i] = NULL;
20
 
21
delete *pContainer;
22
// or
23
delete [] m_pParticleList[0];// ???


Только вот с деаллокацией как-то сомнительно. Во втором варианте лучше бы запомнить контейнер.
Кроме того, трюк с выделением непрерывного массива не обязан гарантировать скорость обращения по указателям т.к. есть мнение, что компилятор И процессор могут оптимизировать , но не переходы по указателям...

[i]Добавлено 28-08-2014 в 16:34:


ps: да, delete [] pContainer;

Добавлено 28-08-2014 в 16:54:

PS/2: ШГ какие-то

__________________
Минутка полезного:
Бесплатный UT-подобный Half-Life mod.
Бесплатный редактор для 32-битных текстур. Без дотнета.
Бесплатный IDE для любых компиляторов и ЯП.
Бесплатная Windows-подобная ОС.
Проверка грамматики русского языка.
Чат по hl[fx]: [email protected]

Сообщить модератору | | IP: Записан
Сообщение: 140372

Старое сообщение 28-08-2014 12:54
- За что?
Тема: (Опционально)
Ваш ответ:



Переводчик транслита


[проверить длину сообщения]
Опции: Автоматическое формирование ссылок: автоматически добавлять [url] и [/url] вокруг интернет адресов.
Уведомление по E-Mail: отправить вам уведомление, если кто-то ответил в тему (только для зарегистрированных пользователей).
Отключить смайлики в сообщении: не преобразовывать текстовые смайлики в картинки.
Показать подпись: добавить вашу подпись в конец сообщения (только зарегистрированные пользователи могут иметь подписи).

Временная зона GMT. Текущее время 20:58. Новая тема    Ответить
  Предыдущая тема   Следующая тема
HLFX.Ru Forum HLFX.Ru Forum > Наш форум > Технические вопросы > [CPP] this << F1 // OOP: субклассы в массивах
уже полгода я не программирую. толстый стал как пельмень...
Версия для печати | Отправить тему по E-Mail | Подписаться на эту тему

Быстрый переход:
Оцените эту тему:

Правила Форума:
Вы not можете создавать новые темы
Вы not можете отвечать в темы
Вы not можете прикреплять вложения
Вы not можете редактировать ваши сообщения
HTML Код ВЫКЛ
vB Код ВКЛ
Смайлики ВКЛ
[IMG] Код ВКЛ
 

< Обратная связь - HLFX.ru >

На основе vBulletin
Авторское право © 2000 - 2002, Jelsoft Enterprises Limited.
Дизайн и программирование: Crystice Softworks © 2005 - 2024