Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/vim/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何防止在多个向量中添加对象?_C++_Algorithm_Design Patterns_Vector_Data Structures - Fatal编程技术网

C++ 如何防止在多个向量中添加对象?

C++ 如何防止在多个向量中添加对象?,c++,algorithm,design-patterns,vector,data-structures,C++,Algorithm,Design Patterns,Vector,Data Structures,有些对象是可绘制的,有些对象是可移动的 所有可移动的物体都可以移动。 我将所有可绘制对象存储在名为drawables的向量中,将可移动对象存储在名为movables的向量中。 我还有向量ships和Bullet,它们分别包含Ship和Bullet类型的对象。 Ship和Bullet都是可移动的 下面是这些类的结构: class Drawable { public: void draw(); }; class Movable : public Drawable { public:

有些对象是
可绘制的
,有些对象是
可移动的

所有可移动的物体都可以移动。
我将所有可绘制对象存储在名为
drawables
的向量中,将可移动对象存储在名为
movables
的向量中。 我还有向量
ships
Bullet
,它们分别包含
Ship
Bullet
类型的对象。
Ship
Bullet
都是
可移动的

下面是这些类的结构:

class Drawable {
public:
    void draw();
};

class Movable : public Drawable {
public:
    void move();
}

class Ship : public Movable {
public:
    Ship();
}

class Bullet : public Movable {
public:
    Bullet();
}
向量声明如下:

std::vector<Drawable*> drawables;
std::vector<Movable*> movables;
std::vector<Ship*> ships;
std::vector<Bullet*> bullets;
我创建了单独的
drawables
movables
向量,因为我有一个
draw()
函数,它调用
drawables
向量中所有对象的
draw()
方法。类似地,我有一个
move()
函数,它调用
movables
向量中所有对象的
move()
方法

我的问题是,如何更改结构以防止在不同的向量中添加相同的内容。一旦目标完成,我还需要从所有向量中删除对象。
例如,一旦子弹击中某人或移出屏幕,我必须在所有三个向量中搜索后将其从向量
drawables
movables
bullets
中删除。
似乎我没有使用正确的方法来存储这些对象。请提出一个替代方案


这似乎更像是一个软件工程问题,而不是一个编码问题。如果有必要,请将问题转移到其他论坛。

既然所有
可移动的
船舶
子弹
都是
可绘制的
,为什么不将
可绘制的
项目作为一个向量,并在其中添加所有不同的类?您将只有一个指向所有不同实例的指针,并且只有这些指针的一个向量。然而,这个解决方案可能需要将
可绘制的
变成一个抽象类。

假设您使用的是一个相当现代的编译器,这正是存在的原因

问题是你不知道哪个向量拥有这个对象,所以你不知道该删除哪个
shared_ptr
为您提供以下功能:它管理对象的生存期,并在销毁对对象的最后一次引用后将其删除

要创建新的
装运
,可以执行以下操作:

auto ship = std::make_shared<Ship>();

drawables.push_back(ship);
movables.push_back(ship);
ships.push_back(ship);
auto ship=std::make_shared();
可抽出式。向后推(船);
动产。推回(船舶);
船。推回(船);

此时,
ship
有4个引用(每个向量一个引用,
ship
变量本身)。一旦它从所有三个向量中删除并且局部变量超出范围,它将自动被删除。

如果您要维护一个包含(指向)特定类型的所有对象的容器,您可能需要采用RAII方法。将对象的构造函数添加到容器中,并将析构函数从容器中移除。您还需要确保没有其他内容会修改容器,因此它应该是类的私有(静态)成员,并使用公共方法提供只读访问

更好的是,将此逻辑移到它自己的类中,以便可以重用。这也将允许您现有的容器保持专注于它们当前所做的事情。他们只需要助手类类型的新数据成员

为了简化移除,我会考虑使用<代码>列表>代码>而不是<代码>向量<代码>。此外,可能值得使用

reference\u wrapper
而不是指针。指针可以有空值。虽然您可以记录容器将没有空指针,但是
reference\u包装器
不需要额外的文档就可以传达这一点

为了让您开始,这里是一个可以使用的助手类模板的开始

template <class T>
class All {
        using ListType = std::list< std::reference_wrapper<T> >;

    private:
        static ListType the_list;
        // A list's iterators are rarely invalidated. For a vector, you would
        // not store an iterator but instead search when removing from the_list.
        typename ListType::iterator list_it;

    public:

        // Read-only access to the list.
        static const ListType & list() { return the_list; }

        // Construction
        ListAll() : list_it(the_list.end()) {}  // If this constructor is needed
        explicit ListAll(T & data) : list_it(the_list.insert(the_list.end(), data)) {}

        // Destruction
        ~ListAll() { if ( list_it != the_list.end() ) the_list.erase(list_it); }

        // Rule of 5
        // You should also define or delete the copy constructor, move constructor,
        // copy assignment, and move assignment.

        // If you need the default constructor, then you probably want a method like:
        //void set(T & data);
};
template <class T>
typename All<T>::ListType All<T>::the_list{};
模板
全班{
使用ListType=std::list;
私人:
静态列表键入_列表;
//列表的迭代器很少会失效
//不存储迭代器,而是在从列表中删除时进行搜索。
typename ListType::迭代器列出它;
公众:
//对列表的只读访问。
static const ListType&list(){返回_list;}
//建筑
ListAll():如果需要此构造函数,请列出它(list.end()){}//
显式ListAll(T&data):list_it(the_list.insert(the_list.end(),data)){
//毁灭
~ListAll(){if(list_it!=the_list.end())the_list.erase(list_it);}
//第5条规则
//还应定义或删除复制构造函数、移动构造函数、,
//复制分配和移动分配。
//如果需要默认构造函数,则可能需要以下方法:
//无效集(T&data);
};
模板
typename All::ListType All::_列表{};

名字往往很难找到。我根据需要迭代的内容命名了这个模板,例如:
All::list()

你能展示更多的代码吗?包括你的声明吗?@Galik添加了向量和类的声明查找实体组件系统,这是游戏事实上的标准结构。你的问题包含矛盾。在文本中,您声明“所有可绘制对象都是可移动的”,但代码表示相反:
可移动
源于
可绘制
,这意味着所有可移动对象都是可绘制的。至于实际问题:为什么首先有不同的向量?如果你的理由是好的,那么也许同样的理由也可以。(因为您存储的是指针而不是副本,所以开销不是很大。)有一些方法可以使向量更易于维护,但首先您需要确定您想要什么。可能有
template <class T>
class All {
        using ListType = std::list< std::reference_wrapper<T> >;

    private:
        static ListType the_list;
        // A list's iterators are rarely invalidated. For a vector, you would
        // not store an iterator but instead search when removing from the_list.
        typename ListType::iterator list_it;

    public:

        // Read-only access to the list.
        static const ListType & list() { return the_list; }

        // Construction
        ListAll() : list_it(the_list.end()) {}  // If this constructor is needed
        explicit ListAll(T & data) : list_it(the_list.insert(the_list.end(), data)) {}

        // Destruction
        ~ListAll() { if ( list_it != the_list.end() ) the_list.erase(list_it); }

        // Rule of 5
        // You should also define or delete the copy constructor, move constructor,
        // copy assignment, and move assignment.

        // If you need the default constructor, then you probably want a method like:
        //void set(T & data);
};
template <class T>
typename All<T>::ListType All<T>::the_list{};