创建一个包含该类所有实例的静态成员容器的类?

Posted

技术标签:

【中文标题】创建一个包含该类所有实例的静态成员容器的类?【英文标题】:Creating a class with a static member container holding all instances of said class? 【发布时间】:2013-05-11 20:26:39 【问题描述】:

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

上下文是一个游戏,其中对象在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;

【问题讨论】:

这应该不会造成问题。你还有3个盒子。您只是将Box_2 分配给Box_1 代码确实有效,但退出前崩溃。 啊,我明白了,问题出在iter 成员上。 【参考方案1】:

你违反了三/五规则。

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

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

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

#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;

顺便说一句:整个设计可能是一个错误。上面的代码在相对微观的层面上涵盖了错误,但没有解决设计的基本问题。

【讨论】:

对替代方法有什么建议吗? 一个包含游戏中使用的[指向]对象集合的游戏就可以了。这是一款包含一系列毫无意义的游戏 (IMO) 的游戏。

以上是关于创建一个包含该类所有实例的静态成员容器的类?的主要内容,如果未能解决你的问题,请参考以下文章

静态成员和继承

调用非静态成员函数而不创建实例

静态类成员python

static变量以及方法

Singleton类的优势是啥? [复制]

Java静态类