12

I am new to C++.
I have a class like this:

class CodeTest
{
private:
    static const int TOTAL=100;
};

Is TOTAL a declaration or a definition?

When I was reading Scott Meyer's book, it was mentioned that in the implementation file we need to define something like:

const int CodeTest::TOTAL;

Why is this required?

Marc Mutz - mmutz
  • 22,883
  • 10
  • 72
  • 86
Whoami
  • 12,364
  • 16
  • 75
  • 133
  • Here is necessary input: http://jcatki.no-ip.org/fncpp/Resources – Griwes Jun 24 '12 at 14:54
  • 3
    @Griwes Totally unhelpful. This is a good question. – Konrad Rudolph Jun 24 '12 at 14:58
  • @KonradRudolph, it's well explained in every decent book. C'mon. – Griwes Jun 24 '12 at 14:59
  • 10
    @Griwes Congratulations. You have just explained why Stack Overflow is totally unnecessary. Just buy books. FWIW, it took me *ages* to understand this, even after reading lots of (good (and bad)) C++ books explaining how TUs work. – Konrad Rudolph Jun 24 '12 at 15:01
  • @Griwes Instead of playing at being insulted (and being insulting at the same time), why don’t you try explaining what I’ve read wrong? – Konrad Rudolph Jun 24 '12 at 15:12
  • 1
    +1 for stirring up controversy on a beautiful Sunday afternoon! – Luchian Grigore Jun 24 '12 at 15:17
  • For those of you who may miss Tomalak Geret'kal (http://stackoverflow.com/users/560648/lightness-races-in-orbit), this was discussed on his blog a month ago or so (or at least a closely related topic): http://kera.name/articles/2012/05/whats-different-about-static-members-defined-in-line/ – Michael Burr Jun 24 '12 at 21:16

4 Answers4

10

The declaration in an implementation file outside of the header is required because otherwise every translation unit that includes this header would define its own object (that is, its own storage for the variable).

This would violate the One Definition Rule. A consequence would be e.g. that if the variable was changed in one translation unit, this change would be invisible to other translation units. Now, this isn’t that relevant since the variable is constant. However, taking its address would also yield different pointers in different translation units.

Konrad Rudolph
  • 482,603
  • 120
  • 884
  • 1,141
  • Your answer doesn't make sense, *because* members functions can be *defined* inside the class itself, then why not static members? As I said, the perfect answer is, because the Standard says so. – Nawaz Jun 24 '12 at 15:25
  • And since R Marthino mentioned it in the chat: it would be possible to define a separate instance in each TU with static storage *but this is not what we want* (in general)! We want a *single* instance accessible from all TUs. – Konrad Rudolph Jun 24 '12 at 15:25
  • @Nawaz but those functions are `inline` by definition, so it's not really the same thing. – Luchian Grigore Jun 24 '12 at 15:26
  • @Nawaz Member functions are something totally different, they are *inlined*. See my previous comment which is somewhat related. C++ also does the same for class templates with static variables but once again this creates *distinct* objects. – Konrad Rudolph Jun 24 '12 at 15:26
  • @KonradRudolph: `inline` is just a hint for the compiler, they're not necessarily *inlined*. – Nawaz Jun 24 '12 at 15:27
  • 1
    @Nawaz Nooooo! `inline` is *not* a hint at the compiler, it determines the linkage. Yes, it’s a hint as far as actual *inlining* is concerned but it also determines linkage, such functions aren’t exported and consequently cannot violate ODR. – Konrad Rudolph Jun 24 '12 at 15:29
  • @KonradRudolph: How does linkage (determined by `inline`) help here? – Nawaz Jun 24 '12 at 15:31
  • @Nawaz Internal linkage means that every TU gets a *distinct*, non-conflicting definition. Hence no violation of ODR. But for the purpose of the static class object this also means that every TU gets its own object (with different addresses) which, to repeat, isn’t generally what we want. – Konrad Rudolph Jun 24 '12 at 15:32
  • Oops... Can't remove my downvote (its already locked, which is a bad rule implemented by SO team) – Nawaz Jun 24 '12 at 15:36
  • Thanks to all. Trying to understand everyone's comment. What i have understood is this: static const inside the class, u initialize it or not, does not matter,and considered as a 'declaration', and outside, as per the specification, we need to define, but we can not re-initialize. Is that correct? – Whoami Jun 24 '12 at 15:44
  • I tried following Program: class CodeGuru { public: static const int NUMBERS; }; #include #include "item1.h" using namespace std; const int CodeGuru::NUMBERS; int main ( int argc, char ** argv) { CodeGuru cg; cout < – Whoami Jun 24 '12 at 15:51
  • @Whoami Well, your code *doesn’t* initialise the constant so the compiler is right to complain. – Konrad Rudolph Jun 24 '12 at 16:01
  • Ahh. My mistake, it is true, as per the specification, initialization shall go while declaring, not at the time of definition. :). So, public: static const int NUMBERS=200; Worked well. – Whoami Jun 24 '12 at 16:03
4

Since this stirred up some controversy, I looked in the standard, and @Nawaz is right, I was wrong.

9.4.2/2

If a static data member is of const integral type [...]. The member shall still be defined in a namespace scope if it is used in the program and the namespace scope definition shall not contain an initializer.

So what you have there is a declaration, and the variable is initialized to a value. Outside the class you must define the variable, but not assign a value to it.

The part with const integral type only applies to this particular case - i.e. you can initialize said type inside the class, but all static data members must be defined outside.

To answer the question:

Regardless of whether the definition is or isn't required outside the class (depending on whether you use the member or not), whatever is inside the class (initialized or not) is just a declaration.

Luchian Grigore
  • 236,802
  • 53
  • 428
  • 594
  • `Outside the class you must define the variable` , you must only in case if you require address of that static var! , otherwise you don't need define it :P – Mr.Anubis Jun 24 '12 at 15:13
  • @Mr.Anubis if you don't want valid C++, you're right. However, the standard says so... (if you use it, not only its address) – Luchian Grigore Jun 24 '12 at 15:15
  • 1
    @Mr.Anubis That is far from clear. There is considerable debate over what “used” means in the paragraph Luchian cited. Consequently, the wording for C++11 was modified to make it clear. – Konrad Rudolph Jun 24 '12 at 15:15
  • right, the only question is why Stroustrup says you can use them without taking the address. – unkulunkulu Jun 24 '12 at 15:18
  • 1
    @KonradRudolph there is diff in what he said and what he cited :/ – Mr.Anubis Jun 24 '12 at 15:18
1

First part of the question:

This line: static const int TOTAL=100; is a declaration followed by an initialisation.

TOTAL is an identifier.

Second part of the question

const int CodeTest::TOTAL is required to initialize the variable.

W.K.S
  • 8,845
  • 13
  • 67
  • 115
  • I think that just saying "yes" or "no" is not really constructive. – Eitan T Jun 24 '12 at 15:26
  • TOTAL is not a variable, as the `const` word marks previously. It a constant number, it is treated like any const definition, and the compiler is permitted to allocate space in data areas for it or not. – Luis Colorado Sep 12 '14 at 06:36
0
static const int TOTAL=100; // is a declaration followed by an initialisation.

From the C++ standard section 3.1:

A declaration introduces names into a translation unit or redeclares names introduced by previous declarations. A declaration specifies the interpretation and attributes of these names.

The next paragraph states that a declaration is a definition unless...... it declares a static member within a class definition:

struct X
{
    int a;         // defines a
    static int b;  // declares b
};

You can read more about definition and declaration here: SO: What is the difference between a definition and a declaration?

selfboot
  • 1,223
  • 17
  • 21