在C++中获取类的所有对象
Getting all objects of a class in C++
有没有一种方法可以让我们在C++中获得一个类的所有对象?就像在Python中一样:
class_name.objects.all()
以获取类的所有对象。如果它存在的话,它在C++中的类似物是什么?
你可以自己做,但要确保你知道自己在做什么。
如何:
C++中没有任何东西已经做到了这一点,但自己做这件事很容易。关键是要认识到一个类可以有静态成员变量和函数(即属于整个类的函数,而不是属于该类的单个对象的函数)。
因此,您可以使用某种表或其他数据结构来存储对每个对象的引用。像这样:
class A {
public:
//constructor assigns this object an id based on the static value curID,
//which is common to the class (i.e. the next class to call the constructor
//will be assigned an id thats 1 more than this one
//also, constructor adds the pointer to this object to a static map of ids
//to objects. This way, the map can be queried for the pointer to an object
//that has a particular id
A() {
id = curID++;
objects[id] = this;
}
//copy constructor ensures an object copied from another does not
//take the id of the other object, and gets added to the map
A(const A&) {
id = curID++; //don't want have the same ID as the object we are copying from
objects[id] = this;
x = A.x;
y = A.y;
}
//destructor removes the pointer to this object from the map
~A() {
objects.erase(id);
}
//function to get the map that stores all the objects
static map<int, A*>& GetMapOfObjects() {
return objects;
}
private:
//the following variable is **static**, which means it does not
//belong to a single object but to the whole class. Here, it is
//used to generate a unique ID for every new object that's
//instantiated. If you have a lot of objects (e.g. more than
//32,767), consider using a long int
static int curID;
//this variable is also static, and is map that stores a pointer
//to each object. This way, you can access the pointer to a
//particular object using its ID. Depending on what you need, you
//could use other structures than a map
static map<int, A*> objects;
//this is a (non-static) member variable, i.e. unique to each object.
//Its value is determined in the constructor, making use of curID.
int id;
//these are some other member variables, depending on what your object actually is
double x;
double y;
}
注意:上面的设计是非常基本的,并不完整,但只是为了让您了解如何使用静态成员/函数来实现您所要求的内容。例如,对于要对所有对象执行的操作,例如,实现一个在元素映射中迭代的静态函数可能会更好,而不是获得映射然后进行迭代"外部";。
原因:
我自己从未使用过这种方法,但我能想到的一个潜在用例是,例如,在图形或游戏应用程序中,您可能只想绘制范围中的对象,并同时更改所有对象的某些绘图相关属性,例如颜色或大小。我正在开发一个应用程序,它可能最终需要这样的东西(有点像视觉调试器)。我相信人们可以在评论中提供更多的例子。
为什么不:
当涉及到继承时,情况会变得复杂起来。
- 如果你有一个从a派生的类B(即B"是"a),那么谁应该跟踪B的对象?A中对象的静态成员,或B中类似的对象,或两者兼有
- 让我们说两者都有。那么,如果一个应用于a中所有对象的静态函数在每个对象上调用一个虚拟成员函数,会发生什么呢?如果虚拟函数已在派生类中被重写,则将为类A中被跟踪的所有对象(实际上是B对象)调用该函数。如果在B中的另一个静态函数中再次调用该函数,会发生什么
我不知道有什么方法,但你可以用static
成员实现一个
#include <iostream>
#include <vector>
class MyClass{
private:
static std::vector<MyClass*> objList;
public:
MyClass() {
objList.push_back(this);
}
static std::vector<MyClass*> getAllObjects(){
return objList;
}
};
std::vector<MyClass*> MyClass::objList;
main(){
MyClass m,a;
for (int i=0;i<MyClass::getAllObjects().size();i++){
std::cout<<MyClass::getAllObjects()[i]<<std::endl;
}
}
否,除非您自己实现此机制。默认情况下,它不是由C++语言提供的。
您可以自己很容易地实现此机制。在构造函数中的某种表中注册类,并在析构函数中注销。只要你遵守三条规则,它就会起作用。
当然有。只需使用Factory模式创建和销毁所有对象,然后在Factory实现中,返回将提供的Factory函数中的活动对象集合。
如前所述,C++不提供自动执行此操作的机制。但是(同样已经在注释中说明),您可以使用一个标准库容器来维护创建的对象的列表,然后在构造函数中注册它们,并在析构函数中注销它们。下面的例子展示了一种方法。。。
#include <iostream>
#include <memory>
#include <utility>
#include <map>
#include <algorithm>
#include <iterator>
#include <typeinfo>
#include <vector>
class Object
{
static std::map<const Object*, Object*> objects_;
public:
Object()
{
objects_.insert(std::make_pair(this, this));
}
virtual ~Object()
{
objects_.erase(this);
}
static std::vector<Object*> get_all()
{
std::vector<Object*> o;
o.reserve(objects_.size());
for (auto obj : objects_)
{
o.push_back(obj.second);
}
return std::move(o);
}
template<class Type>
static std::vector<Type*> get_bytype()
{
std::vector<Type*> o;
for(auto obj : objects_)
{
Type *t = dynamic_cast<Type*>(obj.second);
if (t != nullptr)
{
o.push_back(t);
}
};
return std::move(o);
}
void print() const
{
std::cout << "I'm a " << typeid(*this).name() << " object @ " << this << std::endl;
}
};
std::map<const Object*, Object*> Object::objects_;
class Foo : public Object {};
class Bar : public Object {};
int main()
{
std::unique_ptr<Object> o1 = std::unique_ptr<Object>(new Foo());
std::unique_ptr<Object> o2 = std::unique_ptr<Object>(new Bar());
std::unique_ptr<Object> o3 = std::unique_ptr<Object>(new Foo());
std::unique_ptr<Object> o4 = std::unique_ptr<Object>(new Bar());
std::vector<Object*> objects = Object::get_all();
for (auto o : objects)
{
o->print();
}
std::cout << "-----" << std::endl;
std::vector<Foo*> foos = Object::get_bytype<Foo>();
for (auto o : foos)
{
o->print();
}
std::cout << "-----" << std::endl;
std::vector<Bar*> bars = Object::get_bytype<Bar>();
for (auto o : bars)
{
o->print();
}
}
上述示例产生以下输出
我是类Foo对象@003FED00
我是一个类Bar对象@003FED30
我是类Foo对象@003FED60
我是一个类酒吧对象@003FED90我是类Foo对象@003FED00
我是一个类Foo对象@003FED60我是一个类Bar对象@003FED30
我是一个类酒吧对象@003FED90
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- CMake-按正确顺序将项目与C运行时对象文件链接
- 空基优化子对象的地址
- 将对象数组的引用传递给函数
- 你能重载对象变量名本身返回的内容吗
- C++使用整数的压缩数组初始化对象
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 将对象移动到std::shared_ptr
- 代理对象的常量正确性
- 提升 ASIO 无法识别计时器对象
- 将Ref对象作为类成员
- 将包含C样式数组的对象初始化为成员变量(C++)
- 如何返回一个类的两个对象相加的结果
- 使用std::函数映射对象方法
- 是否需要删除包含对象的"pair"?
- 如何在自删除后将对象设置为nullptr
- 迭代时从向量和内存中删除对象
- 构造对象的歧义
- 使用"std::unordereded_map"映射到"std::list"对象