c – 使用包含所述类的所有实例的静态成员容器创建一个类?

我的目标是创建一个类,将从中创建的每个实例添加到静态成员容器中,以便可以轻松访问所有实例.

上下文是一个游戏,其中对象在Game.init()函数中创建,然后添加到容器中.然后Game.update()和Game.Draw()函数遍历容器以访问和操作对象.

我希望构造函数和解构函数能够处理这些任务,而不是手动向容器添加对象或从容器中删除对象.

当复制或分配对象(此代码中的框)时,指针变为无效.使用对象容器而不是指向对象的容器导致过多的副本,我无法使用引用.我正在寻找一些关于如何改进这些代码以避免这些问题的技巧(使用指针到对象的容器不是必需的,实际上我宁愿避免使用指针但是没有设法让它工作没有他们):

#include <list>
#include <iostream>

class Box
{
    private:
        std::list <Box*>::iterator iter;
    public:
        static std::list <Box*> List;
        Box() {
            List.push_front(this);
            iter = List.begin();
            std::cout << "Constructing box." << std::endl;
        }
        ~Box() {
            std::cout << "Trashing box." << std::endl;
            List.erase(iter);
        }
        void lookInside() {
            std::cout << "It's empty." << std::endl;
        };
};

std::list <Box*> Box::List;

int main()
{
    Box Box_1;
    Box Box_2;
    Box Box_3;

    Box_1 = Box_2; // causes problems!

    for (auto iter : Box::List) {
        iter->lookInside();
    }

    std::cout << "The list contains " << Box::List.size() << " boxes." << std::endl;

    return 0;
}

最佳答案 你违反了三/五的规则.

毫无疑问,您需要重载分配和复制构造(至少)以使您的课程按照需要工作.默认的复制构造函数将只复制迭代器,因此您最终将得到包含原始迭代器副本的第二个对象,指向原始对象,因此当任一副本被销毁时,该项将从您的集合中删除.

显然,你想要的是在你的集合中添加一个新对象,并且在完成复制构造时让该对象将迭代器保存到集合中的新对象.

同样,默认赋值运算符会将迭代器从源复制到目标.您可能只想保持迭代器不变(即仍然引用集合中的同一个对象,因为赋值会导致同一个对象保持不同的值).

#include <list>
#include <iostream>

class Box
{
    private:
        std::list <Box*>::iterator iter;
    public:
        static std::list <Box*> List;
        Box() {
            List.push_front(this);
            iter = List.begin();
            std::cout << "Constructing box." << std::endl;
        }
        ~Box() {
            std::cout << "Trashing box." << std::endl;
            List.erase(iter);
        }
        void lookInside() {
            std::cout << "It's empty." << std::endl;
        };

        // JVC: added next two overloads:
        Box &operator=(Box const &src) { 
            // don't assign anything.
            return *this;
        }
        Box(Box const &other) { 
            List.push_front(this);
            iter = List.begin();
            std::cout << "Copy constructing box.\n";
        }
};

std::list <Box*> Box::List;

int main()
{
    Box Box_1;
    Box Box_2;
    Box Box_3;

    Box_1 = Box_2; // No longer causes problem!

    for (auto iter : Box::List) {
        iter->lookInside();
    }

    std::cout << "The list contains " << Box::List.size() << " boxes." << std::endl;

    return 0;
}

暂且不说:整个设计可能是个错误.上面的代码涵盖了相对微观层面的错误,但没有解决设计的基本问题.

点赞