如何在 c++ 中按预定义的顺序循环浏览类实例?



我正在寻找一种干净的方法来从处理嵌入式芯片的类的所有实例中读取数据,按照使用单个函数声明的顺序读取数据,我可以声明是否作为类本身的一部分。

该函数需要检查在我的程序中构造了多少类实例(我想我想出了这部分(,然后检查它们的声明顺序是什么,但我不确定我的策略是最好的方法:

class input_shift_reg
{
public:
input_shift_reg();
int shift_ID; //keeps count of which instance # this is
int data; // stores data from the chip when read
int *ptr_to_data; //
};
input_shift_reg::input_shift_reg()
{
shift_ID = nb_of_input_shift_reg_objects++;
}
void inputShiftSnapShot() //take a 74hc165 snapshot of the data on the 74hc165 and // transfer it via SPI protocol to the arduino
{
PORTD &= ~(1 << loadPin); //ask the chip for a snapshot (this part is working alright)
delay(1);
PORTD ^= (1 << loadPin);
// This is the part that needs to transfer varying on the number of class instances. 
for(int i = 0; i < nb_of_input_shift_reg_objects; i++)
{
// HERE IS MY PROBLEM: it needs to transfer to the data member of each inst in right order
data = SPI.transfer(0x00);
}
}

所以我只需要一种方法让inputShiftSnapShot((检查创建的所有类实例shift_ID成员的值是多少,并按正确的顺序检查每个数据成员的SPI.transfer((。 例:

input_shift_reg shift_1();
input_shift_reg shift_2();
inputShiftSnapShot(); // this would transfer to shift_1.data first, then to shift_2.data second.

我该怎么做??谢谢!

这是一种使用实例指针静态容器的方法。

要记住的一件事是,每次构建/破坏input_shift_reg都会产生副作用,即更新s_instances容器。 也就是说,如果您现有的代码复制这些代码,并将它们按值传递到函数中,那么您将对instancesdeque 进行许多更新。

另一个需要注意的潜在问题是,如果在迭代实例容器时创建/销毁input_shift_reg对象,则会出现类似 reëntrancy 的错误。

template <typename T>
class tracked
{
static std::deque<T*> s_instances; 
public:
static const std::deque<T*>& instances() { return s_instances; }
static std::size_t number_instances() { return s_instances.size(); }
protected:
tracked() 
{ 
s_instances.push_back(this); 
}
~tracked() noexcept()
{ 
auto it = std::find(s_instances.begin(), s_instances.end(), this);
assert(it != s_instances.end());
s_instances.erase(it);
}
};

class input_shift_reg : public tracked<input_shift_reg> {
/*  ...  */
};
void inputShiftSnapShot()
{
// Perform snapshot.
PORTD &= ~(1 << loadPin); 
delay(1);
PORTD ^= (1 << loadPin);
for (input_shift_reg* reg : tracked<input_shift_reg>::instances())
{
// Use `reg` to update instance.
reg->set_data(...);
}
}

如果您不希望静态成员的复杂性,则可以将指针的 deque 设置为普通成员变量,并通过在类似池的对象中调用某些create(...)函数来强制调用方创建input_shift_reg。 在这种情况下,您可能希望使对象不可复制和不可移动,以便池不会与对象不同步。

最新更新