Creating a class with a static member container containing all instances of the specified class?

My goal is to create a class that adds every instance created from it to a static member container so that all instances can be easily accessed.

Context is a game in which objects are created in the Game.init() function and then added to the container. The Game.update() and Game.Draw() functions then go through the container to access and manage objects.

Instead of manually adding or removing objects to / from the container, I would like the constructor and deconstructor to handle these tasks.

Pointers become invalid when objects (Boxes in this code) are copied or assigned, which is a problem. Using the container of the object instead of the container with the pointer-object led to the fact that excessive copies were made, and I could not get this to work with links. I am looking for some tips on how to improve this code to avoid these problems (using a container with an object pointer is not required, in fact, I would prefer to avoid using pointers, but I could not get this to work without them):

 #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 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; } 
+4
source share
1 answer

You break the rule of three / five.

You will undoubtedly need to overload the assignment and create a copy (at least) for your class to work as it wishes. The default copy constructor will simply copy the iterator so that you get a second object containing a copy of the original iterator, pointing to the original object, so when the copy is destroyed, this element will be removed from your collection.

Obviously, you want to add a new object to your collection and have this object while holding the iterator for the new object in the collection when the copy is being built.

Similarly, the default assignment operator will copy the iterator from source to target. You probably just want to leave the iterator unchanged (i.e. still refer to the same object in the collection, since assignment results in the same object having a different value).

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

Aside: this whole project is probably a mistake. The code above covers errors at a relatively microscopic level, but does nothing to fix the underlying design problem.

+2
source

Source: https://habr.com/ru/post/1480283/


All Articles