Page 1 of 1

Static Variables in a Class

Posted: Sun Jul 26, 2009 6:17 pm
by XianForce
Well after reading LazyFoo's tutorial on Particle Engines I decided to add in a simple one myself. I have a few surfaces to be used and I don't want them to be created for every particle, cause that's unnecessary. I tried to declare them as static but I'm having a lot of trouble with them. From what I've read, the static variables don't belong to any instance, and don't even need an instance. I hear they must be initialized to be in scope, but they can't be initialized in the class or a header file. I'm not sure how correct that is, but I'm assuming it's pretty correct.

Anyways, how would someone go about using the static variables in such a way that:

They are not global.
The header file declaring the class is there so that it can be included into other files so other files can use the methods from the Particle class
And the class methods are not re-defined.


I've had some trouble with this, so hopefully someone can point me in the right direction. If global scope is the way to go, tell me, I just hear that that's bad practice =p.

Re: Static Variables in a Class

Posted: Sun Jul 26, 2009 7:42 pm
by MarauderIIC
Integers can be initialized as static inside a class definition.

Code: Select all

class MyClass {
    static int myInt = 1;
};
Other variable types must be initialized after the class definition.

Code: Select all

class MyClass {
    static int myInt = 1;
    static float myFloat;
};

float MyClass::myFloat = 1.234;

Code: Select all

class MyClass {
    static int myInt;
    static float myFloat;
};

int MyClass::myInt = 1;
float MyClass::myFloat = 1.234;
The same methods are used for static const member variables.

This short program that I wrote straight into the forum and haven't tested demonstrates statics:

Code: Select all

#include <iostream>
using namespace std;

/* can be put into a header file */
class MyClass {
public:
    static float myFloat;
};

float MyClass::myFloat = 1.234;
/* end possible header file */

int main() {
    MyClass class1;
    MyClass class2;

    class1.myFloat = 5.678; //set using class1
    cout << class2.myFloat; //output using class2
    MyClass::myFloat = 9.0123; //set using class
    cout << class2.myFloat << endl //output using class2
         << MyClass::myFloat; //output using class
    return 0;
}
Output:

Code: Select all

5.678 //which we set using class 1
9.0123 //which we set using MyClass and output using class2
9.0123 //which we output using MyClass 

Re: Static Variables in a Class

Posted: Sun Jul 26, 2009 9:32 pm
by XianForce
Thanks a ton Mar. That was much more help than I even dreamed of =D

EDIT: Now I'm getting multiple definition errors. I'm guessing because it's at the bottom of the header file I'm including in different places, so it's defined in multiple places/files.

So how do I get around that =p?

Re: Static Variables in a Class

Posted: Mon Jul 27, 2009 1:23 am
by MarauderIIC
Try moving the static initialization out of the header and to the top of your class's associated .cpp file instead (the same file you define its functions in, you know what I mean).

Re: Static Variables in a Class

Posted: Mon Jul 27, 2009 3:23 pm
by XianForce
MarauderIIC wrote:Try moving the static initialization out of the header and to the top of your class's associated .cpp file instead (the same file you define its functions in, you know what I mean).
When I do that I get a segfault because it's initializing it before SDL initializes. It seems if I put it anywhere else so that it does initialize first, I get a redeclaration error =/.

Re: Static Variables in a Class

Posted: Mon Jul 27, 2009 3:57 pm
by andrew
XianForce wrote:EDIT: Now I'm getting multiple definition errors. I'm guessing because it's at the bottom of the header file I'm including in different places, so it's defined in multiple places/files.
Are you using guards in your header files?

Example:

Code: Select all

#ifndef __DEBUG_H__
#define __DEBUG_H__

#include <fstream>

class Debug
{
    public:
        Debug();
        ~Debug();
        void Log(char c[]);
        std::ofstream& operator<<(char c[]);
        std::ofstream& operator<<(int i);
        std::ofstream& operator<<(float f);
        std::ofstream& operator<<(bool b);
        void Endl(int nr);
};

static Debug debug;

#endif      // __DEBUG_H__

Re: Static Variables in a Class

Posted: Mon Jul 27, 2009 4:21 pm
by XianForce
andrew wrote:
XianForce wrote:EDIT: Now I'm getting multiple definition errors. I'm guessing because it's at the bottom of the header file I'm including in different places, so it's defined in multiple places/files.
Are you using guards in your header files?

Example:

Code: Select all

#ifndef __DEBUG_H__
#define __DEBUG_H__

#include <fstream>

class Debug
{
    public:
        Debug();
        ~Debug();
        void Log(char c[]);
        std::ofstream& operator<<(char c[]);
        std::ofstream& operator<<(int i);
        std::ofstream& operator<<(float f);
        std::ofstream& operator<<(bool b);
        void Endl(int nr);
};

static Debug debug;

#endif      // __DEBUG_H__

Yeah I am

Re: Static Variables in a Class

Posted: Mon Jul 27, 2009 4:51 pm
by short
It looks like your still declaring it in the header file. Try the actual .cpp file

Re: Static Variables in a Class

Posted: Mon Jul 27, 2009 5:17 pm
by XianForce
short0014 wrote:It looks like your still declaring it in the header file. Try the actual .cpp file
I've tried in both.

Initializing it in the classes header file produces a multiple declaration. Initializing it in the C++ produces a segfault (same reason for why it can't be global). Initializing it anywhere else produces a redeclaration error.

Re: Static Variables in a Class

Posted: Mon Jul 27, 2009 6:41 pm
by MarauderIIC
Since it seems to be SDL-dependent, initialize it to NULL first and then set it to whatever you want after you've initialized SDL.

Re: Static Variables in a Class

Posted: Mon Jul 27, 2009 7:26 pm
by dandymcgee
XianForce wrote:
short0014 wrote:It looks like your still declaring it in the header file. Try the actual .cpp file
I've tried in both.

Initializing it in the classes header file produces a multiple declaration. Initializing it in the C++ produces a segfault (same reason for why it can't be global). Initializing it anywhere else produces a redeclaration error.
Can you post the relevant code (where you are initializing it in the .cpp file)?

Edit: Mar beat me, try that first. ;)

Re: Static Variables in a Class

Posted: Mon Jul 27, 2009 8:20 pm
by XianForce
MarauderIIC wrote:Since it seems to be SDL-dependent, initialize it to NULL first and then set it to whatever you want after you've initialized SDL.
Tried... I set it to NULL at the top of the .cpp and then I loaded the surface in another function, after SDL is initialized.

I got a redeclaration error from where I loaded it in the function. It said it was already declared in the header file, the line number was the number where I just declared what was in the class. So like:

Code: Select all

class Particle
{
        private:
                static SDL_Surface* surRed;
}

//then over in some other function...
void someFunc()
{
        SDL_Surface* Particle::surRed = load(); // This is a redeclaration of the above.
}

Re: Static Variables in a Class

Posted: Mon Jul 27, 2009 10:42 pm
by dandymcgee
XianForce wrote:
Tried... I set it to NULL at the top of the .cpp and then I loaded the surface in another function, after SDL is initialized.

I got a redeclaration error from where I loaded it in the function. It said it was already declared in the header file, the line number was the number where I just declared what was in the class. So like:

Code: Select all

class Particle
{
        private:
                static SDL_Surface* surRed;
}

//then over in some other function...
void someFunc()
{
        SDL_Surface* Particle::surRed = load(); // This is a redeclaration of the above.
}
Right.

Try this (omit "Particle::" if you're defining surRed inside a member function of the Particle class):

Code: Select all

void someFunc()
{
        Particle::surRed = load();
}

Re: Static Variables in a Class

Posted: Tue Jul 28, 2009 12:33 am
by XianForce
dandymcgee wrote:
XianForce wrote:
Tried... I set it to NULL at the top of the .cpp and then I loaded the surface in another function, after SDL is initialized.

I got a redeclaration error from where I loaded it in the function. It said it was already declared in the header file, the line number was the number where I just declared what was in the class. So like:

Code: Select all

class Particle
{
        private:
                static SDL_Surface* surRed;
}

//then over in some other function...
void someFunc()
{
        SDL_Surface* Particle::surRed = load(); // This is a redeclaration of the above.
}
Right.

Try this (omit "Particle::" if you're defining surRed inside a member function of the Particle class):

Code: Select all

void someFunc()
{
        Particle::surRed = load();
}

That worked, thanks =D

Re: Static Variables in a Class

Posted: Tue Jul 28, 2009 11:00 am
by dandymcgee
XianForce wrote: That worked, thanks =D
You're welcome. 8-)