trouble with selfreset / abstract class

Hello community,

I'm currently messing with some c++ development. My c++ experience equals nearly to zero but I have done a lot of PHP and Java coding before. What I'm trying to acheive is creating a propper object oriented API for a project I'm currently working on. Basically where i got stuck is the implementation of something what could be called a state pattern.

Now the following code shows how I've implemented the inheritance from the base state. It took me quite a while how to do such a thing in c++:

sketch_looper.pde

#include "Looper.h"

Looper *lp;

void setup()
{
  [glow]// delay(100);[/glow]
  pinMode(2, OUTPUT);
  
  // signal that we are in setup
  pinMode(9, OUTPUT);

  digitalWrite(9, HIGH);
  delay(50);
  digitalWrite(9, LOW);
  delay(50); 
  digitalWrite(9, HIGH);
  delay(50);
  digitalWrite(9, LOW);
  delay(50);
  
  lp = &Looper();
}

void loop()
{
  lp->update();
}

Looper.h

#ifndef Looper_h
#define Looper_h

#include "LooperBaseState.h"

class Looper
{
  public:
    Looper();
    void update();
        
  private:
    void setCurrentState(LooperBaseState *s);
    LooperBaseState *_currState;
    [glow]// int foo;[/glow]
};

#endif

Looper.cpp

#include "Looper.h"
#include "LooperBaseState.h"
#include "StompBoxState.h"

Looper::Looper()
{
  setCurrentState(&StompBoxState());
}

void Looper::update()
{
  _currState->update();
}

void Looper::setCurrentState(LooperBaseState *s) {
  _currState = s;
}

LooperBaseState.h

#ifndef LooperBaseState_h
#define LooperBaseState_h

class LooperBaseState
{
  public:
    LooperBaseState();
    virtual void update() = 0;
};

#endif

LooperBaseState.cpp

#include "LooperBaseState.h"

LooperBaseState::LooperBaseState()
{
}

// this must be implemented or compilation of virtual
// functions(abstract classes) will fail ?!?!?!
extern "C" void __cxa_pure_virtual()
{
  while (1);
}

StompBoxState.h

#ifndef StompBoxState_h
#define StompBoxState_h

#include "LooperBaseState.h"

class StompBoxState : public LooperBaseState
{
  public:
    StompBoxState();
    void update();
};

#endif

StompBoxState.cpp

#include "WProgram.h"
#include "StompBoxState.h"

StompBoxState::StompBoxState()
{
}

void StompBoxState::update()
{
  //Serial.println("eee");
  digitalWrite(2, HIGH);
  delay(250);
  digitalWrite(2, LOW);
  delay(250);
}

The code does the following: it just flashes a LED connected to digtal pin 9 when entering setup. then it just goes in endless loop and flashes a LED connected to digital pin 2 endlessly. This seems to work fine as long as i don't add more lines of code.

Commenting in one of the yellow highlighted lines of code results in re-entering setup (indicated by flashing of LED connected to digital pin 9) and bootstrapping the whole thing again.

No clue whats going on here! I'm guessing it has something to do with my abstract base class / virtual functions / pointers. When i don't inherit from the LooperBaseState, just implementing the state directly, everything seems to work rock solid...
I'm using an Arduino Dicimila

So it would be great if one could give me some help. I've already spent ages on this problem and have no clue what to try next...

Thanks in advance,
Holger

Looper *lp;

void setup()
{
..
  lp = &Looper();
...
}

"Looper()" creates an instance of your class ON THE STACK. "&" returns an address to that instance; an address THAT POINTS INTO THE STACK. "lp = " assigns that STACK ADDRESS to a global variable.

The end of "setup" is reached. The destructor for the Looper object is called. The stack frame is released. "lp" now points to an area of the STACK that can and will be used by other routines.

To avoid this problem, don't use pointers to objects (until you have a better understanding of object lifetimes). Use global / simple instances and references...

Looper lp();

void ManageLooper( Looper& aLooper )
{
  // aLooper.whatever();
}

void loop()
{
  lp.update();
  ManagerLooper( lp );
}

Hi Coding Badly,

many thanks for the quick reply and the clarification! Yes this is what makes c++ fun! Feeling as I never had programmed before.
Sadly, when i try your suggestion, i get the following compile error:

In function »void loop()«:
Fehler: Abfrage des Elementes »update« in »lp«, das vom Nicht-Klassentyp »Looper ()()« ist.

which is german and means something (difficult to translate):

Error: calling of element >update< in >lp<, which is of non-classtype >Looper ()()<

What i want to achieve is having an instance of the looper object which is persitent beween loop() invocations....
Thanks again...

Skip the parenthesis:

Looper lp;

Hi drhex,

but this only declares the variable in my understanding. So calling of lp.update() would result in invoking a method of this uninitialized variable (null pointer or something comparable in c++ world).
I would like to have a persistent single instance of my looper object...any ideas?
thnx,
Holger

but this only declares the variable in my understanding.

Looper *lp; would declare a variable of type pointer to Looper that is uninitialized.

Looper lp; declares a variable that IS an object of type Looper. It invokes the constructor to create the instance.

We need to see your revised code to help you with this.

Ok, got it. "Looper lp" is not just declaration, it is instantiation and assigment....

This is what I'm doing:

#include <WProgram.h>
#include "Looper.h"

void setup()
{
  pinMode(2, OUTPUT);
  
  // signal that we are in setup
  pinMode(9, OUTPUT);

  digitalWrite(9, HIGH);
  delay(50);
  digitalWrite(9, LOW);
  delay(50); 
  digitalWrite(9, HIGH);
  delay(50);
  digitalWrite(9, LOW);
  delay(50);
}

void loop()
{
  Looper lp;
  lp.update();
}

Which works, but an instance of Looper gets created every time loop() is entered. I understand this behavior but it is not what i want. I would like to have "lp" instantiaten once during setup an then reuse this single instance over and over again in the loop() function. This looper object hast to maintain an internal state which i don't want to throw away everytime loop() terminates. How has this to be done?
Many thnx,
Holger

Hi Dave,

if I try as you suggested I get this compile error:

o: In function `setup':
undefined reference to `__cxa_guard_acquire'

mhh, strange....

Hmmm....That code is absolutely standard C++, but I didn't try your whole set of functions. I don't think that message has anything to do with whether it is static or not.

Maybe I will learn not to post even partial programs unless I have tested the whole enchilada. It could happen.

Sorry.

Make it global:

Looper lp
.
.
.
loop()
{
.
.
.
    lp.update()
.
.
.
}

Regards,

Dave

This is what i have so far:

#include <WProgram.h>
#include "Looper.h"

void setup()
{
  pinMode(2, OUTPUT);
  
  // signal that we are in setup
  pinMode(9, OUTPUT);

  digitalWrite(9, HIGH);
  delay(50);
  digitalWrite(9, LOW);
  delay(50); 
  digitalWrite(9, HIGH);
  delay(50);
  digitalWrite(9, LOW);
  delay(50);
}

void loop()
{
  static Looper lp;
  lp.update();
}

which leads to:

o: In function `setup':
undefined reference to `__cxa_guard_acquire'

Regards,
Holger

I don't think that message has anything to do with whether it is static or not.

Tell us, again, why you think you need the _cxa_guard_acquire and what you think it does.

Regards,

Dave

Hi Dave,

the

[b]o: In function `setup':
undefined reference to `__cxa_guard_acquire'[/b]

is an error which I get when i try to compile the example with

....
void loop()
{
  static Looper lp;
  lp.update();
}

Trying the example you suggested earlier:

Make it global:

Code:

Looper lp
.
.
.
loop()
{
.
.
.
    lp.update()
.
.
.
}

will result in a selfreset when calling looper.update().

As I mentioned in my first post:

o clue whats going on here! I'm guessing it has something to do with my abstract base class / virtual functions / pointers. When i don't inherit from the LooperBaseState, just implementing the state directly, everything seems to work rock solid...

I belive it has something to do with the implementation of the other classes which may have some strange side effects.

Your global example will work when I'am changing my code as mentioned in my quote above. Only a single Instance of looper gets created.

So, I really belive it is my implementation of the virtual function/abstract class thing. But this is what I want to acheive...

Thanks,
Holger

Ok, now I'm a step further. I get the thing working when i move the instantiation of StompBoxState from within the constructor of Looper to the global scope of the sketch_looper.pde (which is IMHO a bit ugly).

Looper.cpp

#include <WProgram.h>
#include "Looper.h"
#include "LooperBaseState.h"
#include "StompBoxState.h"

Looper::Looper()
{
  [glow]moved the following line to sketch_looper.pde
  ////setCurrentState(&StompBoxState());///[/glow]
}

void Looper::update()
{
  _currState->update();
}

void Looper::setCurrentState(LooperBaseState *s) {
  _currState = s;
}

sketch_looper.pde

#include <WProgram.h>
#include "Looper.h"
#include "StompBoxState.h"

Looper lp;
[glow]StompBoxState sbs;[/glow]

void setup()
{
  Serial.begin(9600);
  pinMode(2, OUTPUT);
  
  // signal that we are in setup
  pinMode(9, OUTPUT);

  digitalWrite(9, HIGH);
  delay(50);
  digitalWrite(9, LOW);
  delay(50); 
  digitalWrite(9, HIGH);
  delay(50);
  digitalWrite(9, LOW);
  delay(50);
  
 [glow] lp.setCurrentState(&sbs);[/glow]
}

void loop()
{
 lp.update();
}

Then additionally giving the setCurrentState method public access in the appropriate Looper.h header.

In my understanding the problem must be the instantiation of StompBoxState in Looper constructor. Now it lives on global scope and doesn't get thrown away after termination of loop(). Does anybody know a possibility to instantiate a persistent object inside an instance of a class? Any help appreciated...
Thnx in advance,
Holger

The clue to the problem is exactly as Coding Badly (who, despite his handle, know what he is talking about) explained in reply #1. The &StompBoxState is a local variable that goes out of state as soon as the call to Looper() ends.

The solution is as explained in reply #1.

I just don't understand the solution pointed out in in reply #1. I can't see how this code could solve my problem regarding the lifetime of StompBoxState contained in class Looper.

In the meantime I found something that seems to fix my problem.

Adding/altering the highlighted lines:

#include <stdlib.h>
#include "Looper.h"

[glow]#include <stdlib.h> // for malloc and free
void *operator new(unsigned int size_) { return malloc(size_); }
void operator delete(void *p) { free(p); }[/glow]

Looper lp;

void setup(){
  pinMode(9, OUTPUT);
  
  digitalWrite(9, HIGH);
  delay(50);
  digitalWrite(9, LOW);
  delay(50); 
  digitalWrite(9, HIGH);
  delay(50);
  digitalWrite(9, LOW);
  delay(50);
}

void loop()
{
  lp.update();
}
#include "Looper.h"
#include "LooperBaseState.h"
#include "StompBoxState.h"

Looper::Looper()
{
[glow]    setCurrentState(new StompBoxState());[/glow]
}

void Looper::update()
{
  _currState->update();
}

void Looper::setCurrentState(LooperBaseState *s) {
  _currState = s;
}

Now everything works as expected!
Many thanks for the help,
cheers,
Holger