您可以自己执行此操作,但请确保您知道自己在做什么。
如何:
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;
}
A& operator=(const A&) {
id = curID++;
objects[id] = this;
x = A.x;
y = A.y;
return *this;
}
//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;
}
注意:上述设计非常基本且不完整,只是为了让您了解如何使用静态成员/函数来实现您所要求的功能。例如,对于您想要对所有对象执行的操作,例如,最好实现一个遍历元素映射的静态函数,而不是获取映射然后在“外部”进行迭代。
为什么:
我自己从未使用过这种方法,但我能想到的一个潜在用例是,例如在图形或游戏应用程序中,您可能只想绘制范围内的对象并一次性更改所有对象的某些绘图相关属性,例如颜色或大小。我正在开发一个最终可能需要这样的应用程序(一种可视化调试器)。我相信人们可以在 cmets 中提供更多示例。
为什么不:
当涉及到继承时,情况会变得复杂。
- 如果您有一个派生自 A 的 B 类(即 B“是”A),那么谁应该跟踪 B 的对象? A 中的对象的静态成员,或 B 中的类似对象,或两者兼而有之?
- 让我们说两个。那么如果一个适用于 A 中所有对象的静态函数在每个对象上调用一个虚拟成员函数会发生什么?如果虚函数已在派生类中被覆盖,则将为 A 类中跟踪的所有实际上是 B 对象的对象调用该函数。如果你在 B 中的另一个静态函数中再次调用该函数会发生什么?