static methods and members

I've been developing a library and I would like to add a static member to the library. I'm a bit rusty on C++ and have been using mostly Java.

In Java it's quite straight forward as the code is incorporated into the class, however it seems that with Arduino the implementation and definition must be seperate.

I've searched around but not found a complete example that works for me.

In my class I would like to add a static pointer to another object type, I prefixed the declaration with the keyword static.

When I reference the member I prefix the member with the class name and '::' instead or '.'

For example:

class clsDemo {
private:
  static Adafruit_NeoPixel* mpobjNeoPixels;
  static uint8_t mu8NumPixels;

...
  static void setNeoPixels(Adafruit_NeoPixel* pobjPixels, uint8_t u8NumPixels);
}

Then in the class itself I have the implementation of the function:

void clsDemo::setNeoPixels(Adafruit_NeoPixel* pobjPixels,uint8_t u8NumPixels) {
  mpobjNeoPixels = pobjPixels;
  mu8NumPixels = u8NumPixels;                            
}

When I try to compile this I errors to undefined references for 'clsDemo::mpobjNeoPixels' and 'clsDemo::mu8NumPixels'.

Can anyone show me the correct syntax?

Thank you

Make your mind up. chose one class name and stick to it. clsDemo or clsFader Make both the same and it compiles :slight_smile:

Sorry, that was a cut and paste error, for the purposes of this post the class name is clsDemo. I've edited and corrected the post, the question is still the same.

Resolved:
I didn't initialise the static members, after doing this it compiled without any errors.

I haven't done any C++ for several years.

SPlatten:
Resolved:
I didn't initialise the static members, after doing this it compiled without any errors.

I haven't done any C++ for several years.

Told you :stuck_out_tongue:

In Java it's quite straight forward as the code is incorporated into the class, however it seems that with Arduino the implementation and definition must be seperate.

That should read: with C++ the implementation and definition must be seperate


When you define a class you are defining something abstract. It doesn't exist yet.

For example:

class foo
  {
  public:
    int counter;
    
  };

At this stage we know what foo looks like however there is no instance of foo here. Nor does counter exist (as it is part of foo).

If we make an instance of foo then it exists, as does counter:

class foo
  {
  public:
    int counter;
    
  };
  
void setup ()
  {
  foo bar;
  Serial.begin (115200);
  Serial.println (bar.counter);
  }  // end of setup

void loop ()  { }

We can use bar.counter because bar (an instance of foo) exists.

If we make counter static, things change a bit.

class foo
  {
  public:
    static int counter;
    
  };

Neither foo nor counter exists.

But now if we make an instance of foo we still have a problem:

class foo
  {
  public:
    static int counter;
    
  };
  
void setup ()
  {
  foo bar;
  Serial.begin (115200);
  Serial.println (bar.counter);
  }  // end of setup

void loop ()  { }

Error:

sketch_nov15a.cpp.o: In function `setup':
/home/nick/Development/arduino-1.0.6/sketch_nov15a.ino:12: undefined reference to `foo::counter'

Since counter is now static it is not part of the instance "bar". So it has to be created separately.

int foo::counter;

Add that to the above sketch and it compiles OK.

class foo
  {
  public:
    static int counter;
    
  };
  
int foo::counter;

void setup ()
  {
  foo bar;
  Serial.begin (115200);
  Serial.println (bar.counter);
  }  // end of setup

void loop ()  { }

In short, non-static members belong to an instance of the class, static members have to be defined somewhere.

They don't get auto-created because the class is generally in a .h file, which is often included into lots of compilation units. If the compiler created foo::counter for you automatically you would then get a linker error: duplicate foo::counter.

So, you choose where to put foo::counter, which would be in a .cpp file, and in only one of them.

Most static data has to be defined elsewhere as Nick points out. There is an exception though...

A member which is static, constant, and an integral data type can be defined inline with the class declaration.

struct foo{
  static const float bar = 1.0f;
};

In C++11, this improves to allow arrays of constant integrals.

This may be of little value to your app, however now you know.