40

I am starting to learn C++ and Qt, but sometimes the simplest code that I paste from a book results in errors.

I'm using g++4.4.2 on Ubuntu 10.04 with QtCreator IDE. Is there a difference between the g++ compiler syntax and other compilers? For example when I try to access static members something always goes wrong.

#include <iostream>
using namespace std;
class A
{
   public:
      static int x;
      static int getX() {return x;}
};
int main()
{
   int A::x = 100; // error: invalid use of qualified-name 'A::x'
   cout<<A::getX(); // error: : undefined reference to 'A::x'
   return 0;
}

I think it's exactly the same as declared here and here (isn't it?). So what's wrong with the above code?

mrflash818
  • 930
  • 13
  • 24
sorush-r
  • 10,490
  • 17
  • 89
  • 173

9 Answers9

58

You've declared the static members fine, but not defined them anywhere.

Basically what you've said "there exists some static member", but never set aside some memory for it, you need:

int A::x = 100;

Somewhere outside the class and not inside main.

SeasonalShot
  • 2,357
  • 3
  • 31
  • 49
Flexo
  • 87,323
  • 22
  • 191
  • 272
  • 1
    Isn't this a declaration: static int getX(){return x;}? – sorush-r Nov 05 '10 at 09:11
  • 1
    In that context it's declaring and defining getX() at the same time. Without the {return x;} it would be just a declaration. The definition is "the bit that makes it work" which is an implementation or some actual storage. – Flexo Nov 05 '10 at 09:12
14

Section [9.4.2]

Static Data Members

The declaration of a static data member in its class definition is not a definition and may be of an incomplete type other than cv-qualified void. The definition for a static data member shall appear in a namespace scope enclosing the member’s class definition. In the definition at namespace scope, the name of the static data member shall be qualified by its class name using the :: operator

Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
11

You need to define the static member variable of the class outside the class as static member variables require declaration as well as definition.

#include <iostream>
using namespace std;
class A
{
   public:
      static int x;
      static int getX() {return x;}
};

int A::x;         // STATIC MEMBER VARIABLE x DEFINITION

int main()
{
   A::x = 100;    // REMOVE int FROM HERE
   cout<<A::getX();
   return 0;
}
Shubham Singh
  • 111
  • 1
  • 4
9

Try:

#include <iostream>
using namespace std;
class A
{
   public:
      // This declares it.
      static int x;
      static int getX(){return x;}
};

// Now you need an create the object so
// This must be done in once source file (at file scope level)
int A::x = 100;


int main()
{
   A::x = 200;
   // Notice no 'int' keyword before A::x on this line. You can modify A::x

   cout<<A::getX(); // Should work
   return 0;
}
Martin York
  • 257,169
  • 86
  • 333
  • 562
  • Ok. it works. but for template classes, gives this error: too few template-parameter-lists. (I write int SP::free = 100;) – sorush-r Nov 05 '10 at 11:35
  • 1
    @Sorush Rabiee: Sorry I am not psychic. You are going to have to show some code that demonstrates the problem. – Martin York Nov 05 '10 at 15:48
3

Try this example:

#include<iostream>
using namespace std;

class check
{
        static int a;
    public:
        void change();
} ;
int check::a=10;
void check::change()
{
    a++;
    cout<<a<<"\n";
}

int main()
{

    int i,j;
    check c;
    check b;
    c.change();
    b.change();
    return 0;
}
Cullub
  • 2,901
  • 3
  • 30
  • 47
Naresh
  • 155
  • 1
  • 9
  • 1
    Why can't we just write check::a = 10; (without "int" specifier)? I mean, check::a was already declared as int – Maksim Gayduk Mar 31 '17 at 11:01
  • The syntax for defining a non const static variable outside the class is "Return_type class_name :: static_variable = Initialization ". if we miss the return type, compiler throws syntax error. The same is applicable for defining a member function outside the class – Eswaran Pandi Aug 01 '17 at 11:32
3

The definition of static member variables must live at file scope, i.e. outside all functions, etc.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
3

You can use the inline keyword since c++ 17 in front of static members to avoid a definition outside of class scope. Your code should now look like this:

#include <iostream>
using namespace std;
class A
{
   public:
      inline static int x;
      static int getX() {return x;}
};
int main()
{
   A::x = 100;    //Works now
   cout<<A::getX()<<'\n';
   return 0;
}
felix_1
  • 31
  • 1
  • 2
1

Now you have worked out how to use static class members I will advise you that you should generally use them only in the following circumstances:

  • For use in templates. So in your example you could have GetX() in different classes and in a template somewhere you would use

    template< typename T >
    int func()
    {
        return T::GetX();
    }
    

    although obviously more elaborate. But here your static function being in a class serves a purpose.

  • Where the function needs access to the class, i.e. to private members. You could make it a friend but you may as well make it static. Often the case in callbacks.

The rest of the time you can probably use compilation-unit level functions and variables which has the advantage of taking your members out of the header (particularly if they are private). The less implementation detail you give the better.

thkala
  • 84,049
  • 23
  • 157
  • 201
CashCow
  • 30,981
  • 5
  • 61
  • 92
0

Case 1: static variable

As we all know, defining a static variable inside a class which will throw compilation error. E.g. below

class Stats
{
  public: 
     static int AtkStats[3];
     *static int a =20;*        // Error: defining a value for static variable
};

int Stats::AtkStats[3] =  {10, 0, 0};

Output:

error: ISO C++ forbids in-class initialization of non-const static member 'Stats::a'

Case 2: const static variable

For const static variable, we can define a value either inside a class or Outside class.

class Stats
{
  public: 
     static const int AtkStats[3];
     static const int a =20;        // Success: defining a value for a const static
};

const int Stats::AtkStats[3] =  {10, 0, 0};

const int Stats::a = 20;        // we can define outside also

Output:

Compilation success.
Eswaran Pandi
  • 602
  • 6
  • 10