Объекты разных классов в одном векторе? - PullRequest
5 голосов
/ 08 июня 2011

В моем коде у меня есть набор объектов:

class Sphere { ...
class Plane { ...
...

И мне нужно использовать их коллекцию (все они будут разных типов) в vector.Как бы я добавил объекты разных классов в vector?

Ответы [ 6 ]

8 голосов
/ 08 июня 2011

Сфере и Плоскости потребуется общий базовый тип, или ваш вектор должен состоять из void*.

Общий базовый тип (лучше):

class Shape { ... };
class Sphere : public Shape { ... };
class Plane : public Shape { ... };

std::vector<Shape*> shapes;

или void* (не очень):

std::vector<void*> shapes;
7 голосов
/ 08 июня 2011

Классы должны иметь общий базовый класс, например:

class MyBase { };
class Sphere : public MyBase { };
class Plane : public MyBase { };

Затем, чтобы хранить полиморфные объекты в векторе, вы должны хранить указатель на них (поскольку они могут быть разных размеров).из базового класса).Я рекомендую использовать std::shared_ptr<MyBase> или std::unique_ptr<MyBase> (или использовать Boost, если C ++ 0x недоступен).

std::vector<std::shared_ptr<MyBase> > v;
v.push_back<std::shared_ptr<MyBase>(new Sphere());
v.push_back<std::shared_ptr<MyBase>(new Plane());

Если общей базы нет, вам придется использовать void* или найдите другой способ сделать это.

5 голосов
/ 08 июня 2011

Создание контейнеров полиморфных типов - это классическое решение, которое имеет свои проблемы. Один из типов должен стать полиморфным только для того, чтобы добавить их в контейнер - не веская причина. Другая проблема - раннее и жесткое соединение, приводящее к более сложному обслуживанию и отсутствию гибкости, просто для того, чтобы добавить их в контейнер - не веская причина. К счастью, в C ++ есть лучшие альтернативы.

Лучшим решением было бы хранение функций, а не самих объектов в контейнерах. Общая причина, по которой вы хотите поместить разные типы в один и тот же контейнер, состоит в том, чтобы выполнять одинаковые действия для всех них, например, Sphere::Draw() или Plane::Draw(). Вместо этого вы можете создать контейнер функций рисования и стереть тип. Э.Г.

vector<function<void()>> drawings;
Sphere s;
Plane p;
drawings.push_back(bind(s, &Sphere::Draw));
drawings.push_back(bind(p, &Plane::Draw));
for(auto I = drawings.begin(); I != drawings.end(); ++i) (*i)();

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

Приведенное выше решение работает только с C ++ 11 , так как требует std :: function ()

1 голос
/ 08 июня 2011
Class Shape{...code...}
Class Sphere : public Shape{...code...}
Class Plane  : public Shape{...code...}

std::vector<Shape*> List;
List.push_back(new Sphere);
List.push_back(new Plane);

или

//Base class to derived class
Shape* Shape_Sphere = new Sphere();
Shape* Shape_Plane  = new Plane(); 

std::vector<Shape*> List;
List.push_back(Shape_Sphere);
List.push_back(Shape_Plane);

и если вы хотите удалить указатели

std::vector<Shape*>::iterator it;

for(it = List.begin(); it != List.end(); ++it)
{
  delete *it;
}

Поскольку вектор хранит экземпляры Shape и Sphere / Plane, производные от базового класса Shape, C ++ позволит это работать

0 голосов
/ 08 июня 2011

Другие посты рассказали вам большую часть того, что вам нужно знать.Я хотел бы добавить, что в boost есть контейнеры-указатели, которые могут быть полезны, поскольку они очищают содержимое, когда они уничтожаются. Повышение ручной

0 голосов
/ 08 июня 2011

Связаны ли объекты опасным образом? Если это не так, то вам, вероятно, не следует.

Если это так, вы захотите прочесть о наследовании .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...