在 C++ 中跟踪 class 个实例化的概念
Concept to keep track of class instantiations in C++
我正在尝试编写一个代码来跟踪我的 class 实例。
每个实例都由 type
(int) 唯一标识。我想要某种地图,将 type
链接到我的 class.
的实例化
我的想法是为此使用静态映射,并且在调用构造函数时每个实例化都会自行注册:
#include <unordered_map>
#include <iostream>
class Dummy {
public:
Dummy(double a, double b, double c, int type);
void GetContents() {std::cout << type_ <<": a: " << a_ << " b: " << b_ << ", c: " << c_ << std::endl;}
private:
const double a_;
const double b_;
const double c_;
const int type_;
};
static std::unordered_map<int, Dummy> Type_Map{{12, Dummy(1, 2, 3, 12)}}; // pre-defined instantiation
Dummy::Dummy(double a, double b, double c, int type) : a_(a), b_(b), c_(c), type_(type) {
Type_Map.insert({type, *this});
};
在这种情况下,似乎一切正常:
int main()
{
Dummy(12, 6, 23, 3);
Dummy(8, 22, -4, 7);
for (auto a : Type_Map) {
std::cout << a.first << ", ";
a.second.GetContents();
}
}
给出正确的输出:
3, 3: a: 12 b: 6, c: 23
7, 7: a: 8 b: 22, c: -4
12, 12: a: 1 b: 2, c: 3
但是,在这个最小示例和我的真实项目中,这似乎是不稳定的。
虽然实例化仍然在构造函数内部的映射中注册,但一旦我离开构造函数,映射条目就会丢失。
我相信这可能与对象尚未正确初始化的构造函数中的 *this
调用有关?这是不明确的行为吗?
有没有更好的概念可以实现我想做的事情?
PS:我真正需要的
代码是这样写的,因为我有一些 StaticData
class 的实例化和 DynamicData
class 的许多实例化。
StaticData
个实例化的内容没有变化(所有成员都是const
),只有少数几个实例化(这对应我最小示例中的Dummy
class) .
然而,有很多DynamicData
实例化。对于每个 DynamicData
实例化,都有一个属于它的特定 StaticData
对象。
我想避免每个 DynamicData
对象都必须携带一个 StaticData
对象。因此,它只带有一个唯一链接到 StaticData
对象的 id。
如果用户想找出哪个 StaticData
属于我的特定 DynamicData
对象,我们可以在映射中查找(这在运行时不会经常发生,但我们仍然需要保留信息)。
显而易见的解决方案是只使用指针。
但是,我希望用户能够使用 id
初始化 DynamicData
对象,而不必将指针传递给 StaticData
对象。
您想要的是一个注册表,一个特定的对象,您可以在其中创建您打算使用的所有 StaticData
对象(连同它们的关联 ID)。如果有人需要特定的 StaticData
配置,他们会将其添加到注册表中。其他代码可以通过 ID 引用注册表中的对象。
重要的一点是它们不会通过构造对象来引用它们。他们从不成为StaticData
;他们要求注册表为一个已经存在的 pointer/reference。所有此类对象的生命周期都在注册表中进行控制和管理,没有其他人可以管理这些事情。
您试图通过将注册表隐藏在 StaticData
的构造函数后面来使注册表隐式化。这是制造生命周期问题的沃土,因为您创建的 StaticData
和存储在注册表中的所有权关系是......模糊的。最好通过直接向注册表询问对象的引用来使其明确。它清楚地表明您可以访问该对象,但您并不拥有它。
你的问题是静态映射在构造函数内部填充,但是在构造函数之外,入口没有了。似乎有两个不同的静态地图实例。您在构造函数内部看到一个实例,在构造函数外部看到另一个实例。
看起来,您在头文件中定义了静态地图。每个包含头文件的 .cpp 文件都将“看到”它自己的静态映射实例。解决方案:制作一个 class 将地图保留为静态成员。如果这不能解决您的问题,请确保您在 .cpp 文件中定义了静态成员,例如:
map TypeRegistry::Type_Map;
我正在尝试编写一个代码来跟踪我的 class 实例。
每个实例都由 type
(int) 唯一标识。我想要某种地图,将 type
链接到我的 class.
我的想法是为此使用静态映射,并且在调用构造函数时每个实例化都会自行注册:
#include <unordered_map>
#include <iostream>
class Dummy {
public:
Dummy(double a, double b, double c, int type);
void GetContents() {std::cout << type_ <<": a: " << a_ << " b: " << b_ << ", c: " << c_ << std::endl;}
private:
const double a_;
const double b_;
const double c_;
const int type_;
};
static std::unordered_map<int, Dummy> Type_Map{{12, Dummy(1, 2, 3, 12)}}; // pre-defined instantiation
Dummy::Dummy(double a, double b, double c, int type) : a_(a), b_(b), c_(c), type_(type) {
Type_Map.insert({type, *this});
};
在这种情况下,似乎一切正常:
int main()
{
Dummy(12, 6, 23, 3);
Dummy(8, 22, -4, 7);
for (auto a : Type_Map) {
std::cout << a.first << ", ";
a.second.GetContents();
}
}
给出正确的输出:
3, 3: a: 12 b: 6, c: 23
7, 7: a: 8 b: 22, c: -4
12, 12: a: 1 b: 2, c: 3
但是,在这个最小示例和我的真实项目中,这似乎是不稳定的。 虽然实例化仍然在构造函数内部的映射中注册,但一旦我离开构造函数,映射条目就会丢失。
我相信这可能与对象尚未正确初始化的构造函数中的 *this
调用有关?这是不明确的行为吗?
有没有更好的概念可以实现我想做的事情?
PS:我真正需要的
代码是这样写的,因为我有一些 StaticData
class 的实例化和 DynamicData
class 的许多实例化。
StaticData
个实例化的内容没有变化(所有成员都是const
),只有少数几个实例化(这对应我最小示例中的Dummy
class) .
然而,有很多DynamicData
实例化。对于每个 DynamicData
实例化,都有一个属于它的特定 StaticData
对象。
我想避免每个 DynamicData
对象都必须携带一个 StaticData
对象。因此,它只带有一个唯一链接到 StaticData
对象的 id。
如果用户想找出哪个 StaticData
属于我的特定 DynamicData
对象,我们可以在映射中查找(这在运行时不会经常发生,但我们仍然需要保留信息)。
显而易见的解决方案是只使用指针。
但是,我希望用户能够使用 id
初始化 DynamicData
对象,而不必将指针传递给 StaticData
对象。
您想要的是一个注册表,一个特定的对象,您可以在其中创建您打算使用的所有 StaticData
对象(连同它们的关联 ID)。如果有人需要特定的 StaticData
配置,他们会将其添加到注册表中。其他代码可以通过 ID 引用注册表中的对象。
重要的一点是它们不会通过构造对象来引用它们。他们从不成为StaticData
;他们要求注册表为一个已经存在的 pointer/reference。所有此类对象的生命周期都在注册表中进行控制和管理,没有其他人可以管理这些事情。
您试图通过将注册表隐藏在 StaticData
的构造函数后面来使注册表隐式化。这是制造生命周期问题的沃土,因为您创建的 StaticData
和存储在注册表中的所有权关系是......模糊的。最好通过直接向注册表询问对象的引用来使其明确。它清楚地表明您可以访问该对象,但您并不拥有它。
你的问题是静态映射在构造函数内部填充,但是在构造函数之外,入口没有了。似乎有两个不同的静态地图实例。您在构造函数内部看到一个实例,在构造函数外部看到另一个实例。
看起来,您在头文件中定义了静态地图。每个包含头文件的 .cpp 文件都将“看到”它自己的静态映射实例。解决方案:制作一个 class 将地图保留为静态成员。如果这不能解决您的问题,请确保您在 .cpp 文件中定义了静态成员,例如:
map