Форум программистов, компьютерный форум CyberForum.ru

Достать нужный объект из контейнера - C++

Восстановить пароль Регистрация
 
Skaarj
2 / 2 / 1
Регистрация: 28.06.2013
Сообщений: 52
28.05.2014, 11:05     Достать нужный объект из контейнера #1
Возник вопрос, отчасти я сам решил(получил нужный результат), но очень коряво.

Мне нужно достать нужный объект из контейнера на абстрактный класс в методах классов наследниках. Если вкратце, то у меня есть контейнер указателей на абстрактный класс, в котором хранятся различные объекты классов наследников, в моём случае это класс "Метеорит" и "Лазер", со временем будут ещё. Хотелось бы реализовать взаимодействие между ними как то так

C++
1
2
3
4
5
6
7
8
9
extern std::vector<CObject*> Objects;
 
    for(int i = 0; i < (int)Objects.size(); i++)
    {
        for(int j = 0; j < (int)Objects.size(); j++)
        {
            Objects[i]->Collision(Objects[j]);
        }
    }
То есть в зависимости от того какой объект в качестве аргумента передаётся, то и происходит с объектами.

Сейчас у меня как ни странно всё работает - пока видов объектов всего 2.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// абстрактный класс
class CObject
{
virtual void Collision(CObject* Object) = 0;
}
// класс наследник
class CLaser : public CObject
{
friend class CMeteor;
    void Collision(CObject* Object);
    bool Collision(CMeteor* Meteor); 
}
 
class CMeteor : public CObject
{
 
}
// Объявления методов CLaser
void CLaser::Collision(CObject* Object)
{
    CMeteor* Meteor;
    Meteor = (CMeteor*)Object;        
 
    if(Collision(Meteor) == true)
        Object->DestroyObject();
 
}
 
bool CLaser::Collision(CMeteor* Meteor)
{
    if(LaserHit(Meteor->Matrix, Meteor->MeteorSpeed, Meteor->MeteorRadius) == true)
        return true;
    else return false;
}

Meteor = (CMeteor*)Object;
Насколько законное такое присваивание типа? Что будет с объектами из контейнера, которые не CMeteor типа? И можно ли каким то образом проверить какой объект какого типа мы получаем в качестве аргумента, чтобы не лепить такие грабли? Чтобы сложность проверки была линейная - N Объектов - N проверок, а не увеличивалась от количества типов содержащихся в контейнере.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
28.05.2014, 11:05     Достать нужный объект из контейнера
Посмотрите здесь:

при вызове конструктора присваивания надо возвращать ссыль на объект или сам объект. Смысл? Значения нужных полей меняютмся и без этого! C++
интерфейс, в методе которого создается объект типа IDictionary и возвращается ссылка на этот объект C++
C++ Как достать указатель на объект из контейнера set
C++ Выбор контейнера
компилятор считает объект l-value, но объект таковым не является C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
28.05.2014, 11:57     Достать нужный объект из контейнера #2
Skaarj, dynamic_cast, но это все не очень честно говоря хорошо. Можно визиторы реализовать, но кол-во визиторов будет зависит от реального кол-ва классов, то есть много кода, если много классов.
По-хорошему в С++ простого решения данной траблы нет.
Skaarj
2 / 2 / 1
Регистрация: 28.06.2013
Сообщений: 52
28.05.2014, 13:10  [ТС]     Достать нужный объект из контейнера #3
Спасибо за наводку. Ввёл новую виртуальную функцию и определил для каждого наследника. В моём случае не так уж и много классов, так что вполне нормальный вариант. И главное dynamic_cast стал работать как надо - до этого выбивал при не совпадение типов
Я так понимаю это и есть визиторы?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class CObject
{
virtual char* ObjectType() = 0;
};
 
class CLaser : public CObject
{
      char* ObjectType() { char *s; s = "Laser"; return s;}
};
 
class CMeteor : public CObject 
{
      char* ObjectType() { char *s; s = "Meteor"; return s;}
};
И проверяю тип
C++
1
2
3
4
5
6
    if(Object->ObjectType() == "Meteor")
    {
        CMeteor* Meteor = dynamic_cast<CMeteor*>(Object);
        if(Collision(Meteor) == true)
            Object->DestroyObject();
    }
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
28.05.2014, 13:36     Достать нужный объект из контейнера #4
Skaarj, Нет, это не визиторы.
ObjectType предельно бесполезен, ибо dynamic_cast вернет 0, если тип не совпадает.

C++
1
2
3
4
if ((CMeteor* Meteor = dynamic_cast<CMeteor*>(Object))
{
    // Object really has type Meteor*.
}
Добавлено через 6 минут
Прочитать про Посетитель можно тут: http://ru.wikipedia.org/wiki/%D0%9F%...D0%B8%D1%8F%29

Добавлено через 3 минуты
Хотя наверное тут лучше будет какая-никакая реализация мультиметодов.
Kuzia domovenok
 Аватар для Kuzia domovenok
1882 / 1737 / 116
Регистрация: 25.03.2012
Сообщений: 5,907
Записей в блоге: 1
28.05.2014, 13:42     Достать нужный объект из контейнера #5
ForEveR, решение есть - выбросить из головы наследование, отделить физику от прочей логики объекта. Например,
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
class BBody{
  leftBound, rightBound, topBound, bottomBound, farBound, nearBound;
}
class CObject{
  virtual BBody getBoundingBody();
//а возможно даже не virtual, а вполне хранящееся в родителе поле BBody body_;
};
 
for(i=lasers.begin(); i!=lasers.end(); ++i)
  for (j=meteors.begin(); j!= meteors.end(); ++j)
    if(Intersects(i->getBoundingBody(), j->getBoundingBody() )){
       //...
    }
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
28.05.2014, 13:47     Достать нужный объект из контейнера #6
Kuzia domovenok, Я не могу уловить суть данного решения, ибо код написан непонятно как. Можно чуть подробнее все же? Если бы BBody был бы enum я бы еще что-то мог понять (хотя это никак не решает проблему и не избавляет от RTTI), но в этом случае как-то нет.
Kuzia domovenok
 Аватар для Kuzia domovenok
1882 / 1737 / 116
Регистрация: 25.03.2012
Сообщений: 5,907
Записей в блоге: 1
28.05.2014, 14:00     Достать нужный объект из контейнера #7
Цитата Сообщение от ForEveR Посмотреть сообщение
Если бы BBody был бы enum я бы еще что-то мог понять (хотя это никак не решает проблему и не избавляет от RTTI), но в этом случае как-то нет.
какой ещё енум? ты не можешь понять, потому что зациклился на своих кастах, ртти, проблеме определения, что метеор, а что лазер и.т.д. и думаешь, что BBody тоже к чему-то из этой области относится.
Объясняю - мой код вообще не эту проблему решает и не отвечает на этот вопрос.
Объясняю далее - каждый объект содержит Bounding Body. Обычный объект, который ни от чего не наследуется, который содержит например, просто AABB метеора. Что не ясно?
Вот когда у тебя пошли использоваться какие-то стрёмные касты и попытки зачем-то выяснить в динамике тип объекта - вот это уж точно говнокод пошёл.
C++
1
2
3
4
5
for(i=lasers.begin(); i!=lasers.end(); ++i)
  for (j=meteors.begin(); j!= meteors.end(); ++j)
    if(Intersects(i->getBoundingBody(), j->getBoundingBody() )){
       //...
    }
вот тут что не ясно может быть и зачем могут понадобиться касты?
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
28.05.2014, 14:05     Достать нужный объект из контейнера #8
Kuzia domovenok, То есть лазеры отдельно, метеоры отдельно, что-то там еще отдельно? Ну, вцелом все ясно. Уход в сторону уютной сишечки, почему бы и нет.

Добавлено через 1 минуту
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Вот когда у тебя пошли использоваться какие-то стрёмные касты и попытки зачем-то выяснить в динамике тип объекта - вот это уж точно говнокод пошёл.
Ничем не обоснованное заявление. Проблемы бывают разные и решаются они по разному.
Kuzia domovenok
 Аватар для Kuzia domovenok
1882 / 1737 / 116
Регистрация: 25.03.2012
Сообщений: 5,907
Записей в блоге: 1
28.05.2014, 14:10     Достать нужный объект из контейнера #9
Цитата Сообщение от ForEveR Посмотреть сообщение
Уход в сторону уютной сишечки, почему бы и нет
это чистейшее ООП! Что по-твоему тогда?
i->getBoundingBody()
Типичная композиция. BoundingBody - поле класса CObject, а от класса CObject наследуются остальные!
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.05.2014, 14:15     Достать нужный объект из контейнера
Еще ссылки по теме:

Может ли объект-член, или объект-элемент достучаться к содержащему его? C++
C++ Наследование контейнера
C++ Как достать объект-контейнер, а не его элемент

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
28.05.2014, 14:15     Достать нужный объект из контейнера #10
Kuzia domovenok, Окей, с доводами согласен. А как это решает проблему ТС? Предоставь пожалста код, который выполняет то что хотел ТС, с теми изменениями которые ты предложил.
Yandex
Объявления
28.05.2014, 14:15     Достать нужный объект из контейнера
Ответ Создать тему
Опции темы

Текущее время: 14:47. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru