单个向量中不同类的对象?

Ble*_*der 5 c++ class vector

在我的代码中,我有一组对象:

class Sphere { ...
class Plane { ...
...
Run Code Online (Sandbox Code Playgroud)

我需要在a中使用它们的集合(它们都有不同的类型)vector.我如何将不同类的对象添加到vector

Duc*_*tro 8

球体和平面需要一个共同的基础类型,或者你的向量需要由void*'s 组成.

通用基类型(更好):

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

std::vector<Shape*> shapes;
Run Code Online (Sandbox Code Playgroud)

或者void*是(不是很好):

std::vector<void*> shapes;
Run Code Online (Sandbox Code Playgroud)


Sve*_*ven 7

这些类需要有一个共同的基类,例如:

class MyBase { };
class Sphere : public MyBase { };
class Plane : public MyBase { };
Run Code Online (Sandbox Code Playgroud)

然后,为了在向量中存储多态对象,必须存储指向它们的指针(因为它们可以与基类不同).我建议使用std::shared_ptr<MyBase>std::unique_ptr<MyBase>(如果C++ 0x不可用则使用Boost).

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());
Run Code Online (Sandbox Code Playgroud)

如果没有共同基础,您必须使用void*或找到不同的方法来执行此操作.

  • 您必须*始终*使用引用或指针来引用多态类型.如果你做`Object target =*object [i];`你的对象被复制到`Object`并丢失其原始类型.你可以做`Object&target =*object [i];`,或`Object*target = object [i];`,这将允许你使用虚函数.要获取特定类型,请使用`Sphere*target = dynamic_cast <Sphere*>(objects [i]);`.如果对象不是Sphere,`dynamic_cast`将返回NULL. (2认同)

Gen*_*yev 5

创建多态类型的容器是一种经典的解决方案,它有自己的问题.其中一种类型必须变成多态才能将它们添加到容器中 - 这不是一个好理由.另一个问题是早期和紧密耦合导致更难以维护和缺乏灵活性,只是为了将它们添加到容器中 - 这不是一个好理由.幸运的是,在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)();
Run Code Online (Sandbox Code Playgroud)

通过这样做,您可以避免强耦合和其他继承问题,并获得更灵活,更通用的解决方案.

以上解决方案仅适用于C++ 11,因为它需要std :: function()