更改一个对象';LinkedList中的s成员更改所有对象 对不起,我对C++很陌生,我正在编写一个ARDIIO草图。< /P>
我想实现一种面向命令的方法,在这种方法中,我有一个命令队列、一个父虚拟/抽象类命令,并且每个实际命令都从这个类继承 为了实现这个队列,我使用从Arduino的库管理器(某种“库存储”)获得的LinkedList库。因此,我:更改一个对象';LinkedList中的s成员更改所有对象 对不起,我对C++很陌生,我正在编写一个ARDIIO草图。< /P>,c++,oop,c++11,arduino,linked-list,C++,Oop,C++11,Arduino,Linked List,我想实现一种面向命令的方法,在这种方法中,我有一个命令队列、一个父虚拟/抽象类命令,并且每个实际命令都从这个类继承 为了实现这个队列,我使用从Arduino的库管理器(某种“库存储”)获得的LinkedList库。因此,我: LinkedList<Command*> queue = new LinkedList<Command*>(); LinkedList队列=新建LinkedList(); 我添加了*因为否则它将无法编译 问题是,我正在使用“new”操作符将命令推
LinkedList<Command*> queue = new LinkedList<Command*>();
LinkedList队列=新建LinkedList();
我添加了*因为否则它将无法编译
问题是,我正在使用“new”操作符将命令推送到队列中。如果我只处理列表中的一个对象,它会正常工作,但目的是在队列中有多个命令,问题是如果我更改实例的成员,它也会更改队列中的所有其他实例,就像所有实例都指向同一个实例一样。当然,变量并不是声明为静态的
我怀疑是因为列表初始化中的**,但老实说,我还没有完全理解C++指针,这只是一个疯狂的猜测。
更新#1:回答molbdnilo请求。下面是一个最小的可复制示例(您需要Luis Llamas创建的LinkedListLib库,可以从Arduino库管理器获得):
#包括
//确定
类命令{
私人:
String state=“NOT_EXEC”;//Estados:NOT_EXEC,NOT_FINISHED,FINISHED
公众:
virtual void init()=0;//Función de inicialización de comando
virtual void exec()=0;//Función de ejeucción del comando
virtual void finish()=0;//Función de finalizado del comando
void setStatus(字符串s){state=s;};
virtual~Command(){};
字符串getStatus(){
返回状态;
}//科曼多庄园酒店
};
类Parpadear:public命令{
私人:
长t;
int c=0;
int stat;
国际密尔;
国际代表;
公众:
Parpadear(整数x,整数y){
密耳=x;
rep=y;
}
void init()重写{
t=millis();
stat=高;
digitalWrite(LED内置,stat);
}
void exec()重写{
如果(毫秒()-t>mil){
stat=stat==高?低:高;
digitalWrite(LED内置,stat);
t=millis();
C++;
}
if(c==rep){
设置状态(“完成”);
}
}
void finish()重写{
}
Parpadear::~Parpadear(){
}
};
//Estados:1=init,2=exec,3=main
常量int INIT=1;//初始化状态
const int EXEC=2;//命令执行状态
常量int MAIN=3;//主循环代码状态
int state=INIT;
初始时间长;
LinkedList队列=LinkedList();
字符串命令结果;
无效设置(){
//伊尼西翁·德阿杜伊诺
pinMode(LED内置,输出);//配置LED表
Serial.begin(9600);
}
void循环(){
//东方公司全球结构控制部部长
开关(状态){
案例初始:
//埃斯塔多斯马奎纳酒店
init_time=millis();//这是一个很好的例子。
state=EXEC;//Realizar transición a ejeucción de comandos。
队列.插入头(新Parpadear(2000,4));
InsertTail(新Parpadear(300,50));
打破
案件执行官:
//可口可乐公司
if(queue.GetSize()>0){
if(queue.GetHead()->getStatus()=“NOT_EXEC”){
queue.GetHead()->init();
queue.GetHead()->setStatus(“未完成”);
}
queue.GetHead()->exec();//ejecta primer comando en la cola
if(queue.GetHead()->getStatus()==“FINISHED”){
//Serial.println(queue.GetHead()->getStatus());
queue.GetHead()->finish();
queue.RemoveAt(0);//Quitar el primer comando de la lista
}
}
打破
主要案例:
打破
}
}
更新#2:关于Botje的问题:
我如何确定这两个实例都在改变
(有关代码参考,请参阅开关盒EXEC)
从父命令类继承的所有命令(在本例中,仅实现类Parpadear)都有一个名为“state”的字符串变量,该变量存储命令的状态,因此每次命令排队时,只有当它完成执行时,该“state”变量才会将其值更改为“FINISHED”(否则将被忽略)“NOT_FINISHED”),这会触发队列从列表中删除命令
使用Arduino的串行监视器工具,我可以看到在排队2个命令后,第一个命令将相应地执行,但一旦第一个命令被删除,第二个命令也会立即被删除。我使用Serial.println为每个命令打印“state”变量,所有这些命令都会导致“FINISHED”“当另一个不应该的时候
还打印了变量“c”,它只是一个计数器,在两种情况下它都等于相同的值(4),因为在第二种情况下“c”甚至还没有被操作过。更改到另一个库解决了这个问题。具有讽刺意味的是,它是由同一位作者开发的 在这种情况下,我使用的是列表而不是LinkedList,有什么区别吗
可能另一个库已经过时,或者以一种模糊的方式处理指针,但是为了记录,我现在使用的库是“ListLib”,也可以从Arduino库管理器中获得请阅读,然后创建一个。您是如何确定队列中的所有其他实例也发生了变化的?代码在哪里?谢谢你们的回答,我更新了问题以解决你们的问题。再次感谢大家!
#include <LinkedListLib.h>
// Definiciones
class Command {
private:
String state = "NOT_EXEC"; // Estados: NOT_EXEC, NOT_FINISHED, FINISHED
public:
virtual void init() = 0; // Función de inicialización de comando
virtual void exec() = 0; // Función de ejecución del comando
virtual void finish() = 0; // Función de finalizado del comando
void setStatus(String s){ state = s;};
virtual ~Command(){};
String getStatus(){
return state;
} // Entrega el estado del comando
};
class Parpadear : public Command{
private:
long t;
int c = 0;
int stat;
int mil;
int rep;
public:
Parpadear(int x, int y){
mil = x;
rep = y;
}
void init() override{
t = millis();
stat = HIGH;
digitalWrite(LED_BUILTIN, stat);
}
void exec() override{
if (millis() - t > mil){
stat = stat == HIGH ? LOW : HIGH;
digitalWrite(LED_BUILTIN, stat);
t = millis();
c++;
}
if(c == rep){
setStatus("FINISHED");
}
}
void finish() override{
}
Parpadear::~Parpadear(){
}
};
// Estados: 1 = init, 2 = exec, 3 = main
const int INIT = 1; // Initialization state
const int EXEC = 2; // Command execution state
const int MAIN = 3; // Main loop code state
int state = INIT;
long init_time;
LinkedList<Command*> queue = LinkedList<Command*>();
String commandResult;
void setup() {
// Inicialización de Arduino
pinMode(LED_BUILTIN, OUTPUT); // Configura LED en tabla
Serial.begin(9600);
}
void loop() {
// Máquina de estados para control global de la estructura orientada a comandos
switch(state){
case INIT:
// Inicialización de la máquina de estados
init_time = millis(); // Obtener el tiempo en el que la máquina de estados se empezó a ejecutar por primera vez.
state = EXEC; // Realizar transición a ejecución de comandos.
queue.InsertHead(new Parpadear(2000, 4));
queue.InsertTail(new Parpadear(300, 50));
break;
case EXEC:
// Ejecución de comandos en cola
if(queue.GetSize() > 0){
if(queue.GetHead()->getStatus() == "NOT_EXEC"){
queue.GetHead()->init();
queue.GetHead()->setStatus("NOT_FINISHED");
}
queue.GetHead()->exec(); // Ejecuta primer comando en la cola
if(queue.GetHead()->getStatus() == "FINISHED"){
//Serial.println(queue.GetHead()->getStatus());
queue.GetHead()->finish();
queue.RemoveAt(0); // Quitar el primer comando de la lista
}
}
break;
case MAIN:
break;
}
}