将所有 class 个实例的列表存储为 class 中的静态数组
Store a list of all class instances as a static array within the class
我确定以前有人问过这个问题,但是这个问题的术语令人困惑,而且我是顶级 C++ 的新手,我什至不确定我是否正确使用它,所以我还没有问过能够找到它以前问过的。如有遗漏请见谅
(如果有人足够专业来纠正我在问题中的语法错误,请这样做,这样我以后可能会更准确;-))
我需要定义一个class,其中一个成员数组存储指向所述class的所有实例的指针。该数组由每个成员都有的整数 id 索引。
因此可以访问:
MyClass testcase = MyClass();
int i = testcase.id;
MyClass* tempVar;
tempVar = MyClass::InstanceRecord[i]; // this is the procedure in ?
应该使用指向新创建的 class 'testcase' 实例的指针填充 tempVar。这样 class 成员可以通过他们的 'id' 成员相互引用。
我的问题在于声明数组 'InstanceRecord'。我无法控制填充数组的顺序(换句话说,创建 class 的实例),并且 ID 号是预定义的 [段落编辑]。因此我需要使用以下形式:(注意:这是在 class 定义中)
static MyClass* InstanceRecord[MAXIMUM_POSSIBLE_INSTANCES] = {x};
为了声明数组,一步填充数组的全宽。这样我就可以在调用 MyClass() (构造函数)期间更改数组给定元素的值。
问题是我不知道如何用尚不存在的内存指针填充数组。有没有好心人给我解释一下我在前面的语句中'='右边的内容,或者给出另一种方法来做到这一点?
编辑:class 定义如下所示:
class MyClass{
Public:
MyClass(string fileName){
// Initialize class members from file data
// including the id member
// list of other members which require a status of True
// before this item has an available of True. id1-id5
// represent id members of other instances of this class.
// these id's all come from hard files.
required_data[] = {id1, id2, id3, id4,id5};
available=0; //boolean false
status=0; //boolean false
// is this the right way to do a vector of pointers?
InstanceRecord[id]= this;
}
MyClass* get_instance_by_id(int i){
return InstanceRecord[i];
}
bool is_available(){
return available;
}
void update_available(){
int sum = 0;
for (int i = 0; i<5 ;i++){
if (InstanceRecord[required_data[i]].status == 1 || required_data[i] == 0){
sum +=1;
}
}
if (sum >=5){
available = 1;
}
}
Private:
int id;
std::vector<MyClass*>InstanceRecord (MAX_INSTANCES, nullptr);
int required_data[5];
bool status;
bool available;
}
编辑:示例数据文件(通常不允许评论,但为清楚起见添加)
Widget Glue Removal Tool // becomes MyClass.name
1251 // becomes MyClass.id
...lots of other stuff... // becomes MyClass.[some_var_name]
14,37,1841,15,27 // becomes the id1...id5 which must be
// status checked to determine this
// object's available flag. These ints
// are the id's (like this 1251) of those
// other instances.
这个数据实际上是我的一个宠物项目,一个电子游戏。 class 表示 "Research Tree" 中的一项,其中必须先完成必要的研究,然后才能使用新主题。树和主题不一定是线性的。在访问项目 47 之前,您可能必须研究项目 20,400,12 和 15(因此 ID 为 20、400、12 和 15 的实例都必须具有状态 = 1,表明它们在项目 47 可用之前已完成= 1 在研究项目选择上显示它 window)。由于研究树是通过读取目录中的每个文件来填充的,因此在非受控序列中,当 [=52 的第一个实例时,我需要用某种空指针(目前假设为 nullptr)填充我的索引向量=] 被创建。我最初的问题是,并且基本上仍然是,如何用这些数据填充向量。我现在知道了
std::vector<MyClass*>InstanceRecord(MAX_POSSIBLE_INSTANCES, X);
应该可以满足我的需求,但是nullptr可以代替这一行的X吗?
工厂 class 巴里的回答,其实教会了我很多,但下一个答案似乎更适合我的需要。在这一点上,我只是想确定迈克尔的答案是否可以简单地修改为:
id=<data read in from file>;
InstanceRecord[id]=this;
在他的回答的第五行和第六行。
正如我所说,我只是 C++ 的浅尝辄止,显然我对术语缺乏正确的理解,因此无法很好地陈述问题,这导致了一些混乱。编译时间来测试这将是巨大的,所以我希望在我开始这个过程之前让它尽可能地没有错误(不是我们所有人)。
我想你想要的是一个对象工厂:
template <typename T>
class Factory {
private:
static std::vector<std::unique_ptr<T>> instances;
public:
static T* create() {
std::unique_ptr<T> obj{new T};
obj->id = instances.size();
instances.emplace_back(std::move(obj));
return instances.back().get();
}
static T* get(size_t idx) const {
return instances[idx].get();
}
};
像这样使用:
MyClass* testcase = Factory<MyClass>::create();
assert(testcase->id == 0);
assert(Factory<MyClass>::get(0) == testcase);
您可以通过将跟踪向量添加为静态实例来完成此操作。
您还需要在销毁时从跟踪向量中删除该项目。如果您从多个线程创建/更新,则需要适当地锁定/解锁它。
如果不加锁的话可能有点像这样
class MyClass{
Public:
MyClass(string fileName){
status=0;
id = instanceRecord.size();
instanceRecord.push_back(this);
}
~MyClass() {
//Clear it so that we dont access invalid data in update_available.
instanceRecord[id]=NULL;
}
static MyClass* get_instance_by_id(int i){
//TODO: Add bounds checking here.
return instanceRecord.get(i);
}
void update_available(){
int sum = 0;
for (int i = 0; i<5 ;i++){
MyClass * instance = instanceRecord[i];
if(instance==NULL)
continue;
if (instanceRecord[required_data[i]].status == 1 || required_data[i] == 0){
sum +=1;
}
}
if (sum >=5){
available = 1;
}
}
private:
int id;
static std::vector<MyClass*>instanceRecord;
...
}
然后您需要添加一个 .cpp
文件来添加静态矢量 - 类似这样。
std::vector<MyClass> MyClass::instanceRecord = std::vector<MyClass>();
如果您需要锁定,那么您需要添加一个静态锁对象,并使用该锁包装对 instanceRecord 的所有访问。
最后一个附带条件是,如果您在 main 之外创建 MyClass
的任何实例,由于使用静态变量,您可能 运行 进入 "static initialization order fiasco"。使用某些单例方法可以解决此问题,但它们会使事情看起来更加复杂,因此在简单情况下不值得。
我确定以前有人问过这个问题,但是这个问题的术语令人困惑,而且我是顶级 C++ 的新手,我什至不确定我是否正确使用它,所以我还没有问过能够找到它以前问过的。如有遗漏请见谅
(如果有人足够专业来纠正我在问题中的语法错误,请这样做,这样我以后可能会更准确;-))
我需要定义一个class,其中一个成员数组存储指向所述class的所有实例的指针。该数组由每个成员都有的整数 id 索引。
因此可以访问:
MyClass testcase = MyClass();
int i = testcase.id;
MyClass* tempVar;
tempVar = MyClass::InstanceRecord[i]; // this is the procedure in ?
应该使用指向新创建的 class 'testcase' 实例的指针填充 tempVar。这样 class 成员可以通过他们的 'id' 成员相互引用。
我的问题在于声明数组 'InstanceRecord'。我无法控制填充数组的顺序(换句话说,创建 class 的实例),并且 ID 号是预定义的 [段落编辑]。因此我需要使用以下形式:(注意:这是在 class 定义中)
static MyClass* InstanceRecord[MAXIMUM_POSSIBLE_INSTANCES] = {x};
为了声明数组,一步填充数组的全宽。这样我就可以在调用 MyClass() (构造函数)期间更改数组给定元素的值。
问题是我不知道如何用尚不存在的内存指针填充数组。有没有好心人给我解释一下我在前面的语句中'='右边的内容,或者给出另一种方法来做到这一点?
编辑:class 定义如下所示:
class MyClass{
Public:
MyClass(string fileName){
// Initialize class members from file data
// including the id member
// list of other members which require a status of True
// before this item has an available of True. id1-id5
// represent id members of other instances of this class.
// these id's all come from hard files.
required_data[] = {id1, id2, id3, id4,id5};
available=0; //boolean false
status=0; //boolean false
// is this the right way to do a vector of pointers?
InstanceRecord[id]= this;
}
MyClass* get_instance_by_id(int i){
return InstanceRecord[i];
}
bool is_available(){
return available;
}
void update_available(){
int sum = 0;
for (int i = 0; i<5 ;i++){
if (InstanceRecord[required_data[i]].status == 1 || required_data[i] == 0){
sum +=1;
}
}
if (sum >=5){
available = 1;
}
}
Private:
int id;
std::vector<MyClass*>InstanceRecord (MAX_INSTANCES, nullptr);
int required_data[5];
bool status;
bool available;
}
编辑:示例数据文件(通常不允许评论,但为清楚起见添加)
Widget Glue Removal Tool // becomes MyClass.name
1251 // becomes MyClass.id
...lots of other stuff... // becomes MyClass.[some_var_name]
14,37,1841,15,27 // becomes the id1...id5 which must be
// status checked to determine this
// object's available flag. These ints
// are the id's (like this 1251) of those
// other instances.
这个数据实际上是我的一个宠物项目,一个电子游戏。 class 表示 "Research Tree" 中的一项,其中必须先完成必要的研究,然后才能使用新主题。树和主题不一定是线性的。在访问项目 47 之前,您可能必须研究项目 20,400,12 和 15(因此 ID 为 20、400、12 和 15 的实例都必须具有状态 = 1,表明它们在项目 47 可用之前已完成= 1 在研究项目选择上显示它 window)。由于研究树是通过读取目录中的每个文件来填充的,因此在非受控序列中,当 [=52 的第一个实例时,我需要用某种空指针(目前假设为 nullptr)填充我的索引向量=] 被创建。我最初的问题是,并且基本上仍然是,如何用这些数据填充向量。我现在知道了
std::vector<MyClass*>InstanceRecord(MAX_POSSIBLE_INSTANCES, X);
应该可以满足我的需求,但是nullptr可以代替这一行的X吗?
工厂 class 巴里的回答,其实教会了我很多,但下一个答案似乎更适合我的需要。在这一点上,我只是想确定迈克尔的答案是否可以简单地修改为:
id=<data read in from file>;
InstanceRecord[id]=this;
在他的回答的第五行和第六行。
正如我所说,我只是 C++ 的浅尝辄止,显然我对术语缺乏正确的理解,因此无法很好地陈述问题,这导致了一些混乱。编译时间来测试这将是巨大的,所以我希望在我开始这个过程之前让它尽可能地没有错误(不是我们所有人)。
我想你想要的是一个对象工厂:
template <typename T>
class Factory {
private:
static std::vector<std::unique_ptr<T>> instances;
public:
static T* create() {
std::unique_ptr<T> obj{new T};
obj->id = instances.size();
instances.emplace_back(std::move(obj));
return instances.back().get();
}
static T* get(size_t idx) const {
return instances[idx].get();
}
};
像这样使用:
MyClass* testcase = Factory<MyClass>::create();
assert(testcase->id == 0);
assert(Factory<MyClass>::get(0) == testcase);
您可以通过将跟踪向量添加为静态实例来完成此操作。 您还需要在销毁时从跟踪向量中删除该项目。如果您从多个线程创建/更新,则需要适当地锁定/解锁它。
如果不加锁的话可能有点像这样
class MyClass{
Public:
MyClass(string fileName){
status=0;
id = instanceRecord.size();
instanceRecord.push_back(this);
}
~MyClass() {
//Clear it so that we dont access invalid data in update_available.
instanceRecord[id]=NULL;
}
static MyClass* get_instance_by_id(int i){
//TODO: Add bounds checking here.
return instanceRecord.get(i);
}
void update_available(){
int sum = 0;
for (int i = 0; i<5 ;i++){
MyClass * instance = instanceRecord[i];
if(instance==NULL)
continue;
if (instanceRecord[required_data[i]].status == 1 || required_data[i] == 0){
sum +=1;
}
}
if (sum >=5){
available = 1;
}
}
private:
int id;
static std::vector<MyClass*>instanceRecord;
...
}
然后您需要添加一个 .cpp
文件来添加静态矢量 - 类似这样。
std::vector<MyClass> MyClass::instanceRecord = std::vector<MyClass>();
如果您需要锁定,那么您需要添加一个静态锁对象,并使用该锁包装对 instanceRecord 的所有访问。
最后一个附带条件是,如果您在 main 之外创建 MyClass
的任何实例,由于使用静态变量,您可能 运行 进入 "static initialization order fiasco"。使用某些单例方法可以解决此问题,但它们会使事情看起来更加复杂,因此在简单情况下不值得。