views:

110

answers:

5

I am getting very confused in some concepts in c++. For ex: I have following two files

//file1.cpp
class test
{
    static int s;
    public:
    test(){s++;}
};

static test t;
int test::s=5;

//file2.cpp
#include<iostream>
using namespace std;
class test
{
    static int s;
    public:
    test(){s++;}
    static int get()
    {
    return s;
    }
};

static test t;

int main()
{
    cout<<test::get()<<endl;
}

Now My question is :
1. How two files link successfully even if they have different class definitions?
2. Are the static member s of two classes related because I get output as 7.

Please explain this concept of statics.

+3  A: 

They link because the linker knows almost nothing about the C++ language. However, if you do this, you have broken the One Definition Rule, and the behaviour of your program will be undefined. writing invalid code is not a good way of learning C++. Also, you seem to be having a lot of questions about static variables - the concept is really not all that complex - which C++ textbook are you using that does not explain it well?

anon
Ok..Now suppose I write same class definition in both files. Then what about my 2nd question? Are static members of both classes related?
Happy Mittal
@Happy There can only be ONE class with the name test, so there can only be ONE static variable. anything else is an artefact produced by the linker.
anon
I am using Thinking in c++ by Bruce Eckel. Actually I was reading schwarz counter technique for static initialization order fiasco, but I couldn't understand the code that was written to explain that technique .If you have that book, can you please explain that code?
Happy Mittal
@Happy If your question is about Schwartz Counters, ask about them specifically. However, although such things exist it is a very, very bad idea to write code that depends on static initialisation order for objects not in the same compilation unit. And it's easy not to do so.
anon
Yes I know it's a bad thing but I just want to undersatnd concept.I will make a seperate thread for schwartz counter but before that I wanted to clear my doubt about this static thing.
Happy Mittal
+1  A: 

The classes are (as far as the linker is concerned) identical. get() is just an inline function the linker never sees.

static in a class doesn't limit the member to file scope, but makes it global for all class instances.

[edit:] You'd get an linker error if you would put int test::s=5; into the second file as well.

+1  A: 

Static is a strange beast in C++, that has different meanings depending on the context.

In File1.cpp, "static int s" in the class definition indicates that s is a static member, that is, is common to all instances of test.

The "static test t", though, has a different meaning: a static global variable only exists in the compilation unit, and will not be visible by other units. This is to avoid linker confusion if you were using the same name for two different things. In modern C++, one would use anonymous namespaces for this:

namespace
{
  test t;
}

This means that t inside File1.cpp and t inside File2.cpp are separate objects.

In File2.cpp, you also defined a static method get: a static method is a method that belongs to the class instead of the instance, and that can only access static members of the class.

A last use of static, that you did not use in your example, is the local static variable. A local static variable is initialised the first time it gets executed, and keeps its value throughout the execution, a bit like a global variable with a local scope:

int add()
{
  static value = 0;
  value++;
  return value;
}

Calling add() repetitively will return 1, then 2, then 3... This local static construct can be useful for local caches for example.

small_duck
A: 
  1. How two files link successfully even if they have different class definitions?

You violated the One Definition Rule (ODR) by defining the same class differently in different translation units. That invokes the dreaded Undefined Behavior. Which means the code is allows to do anything, including, but not limited to, doing what you wanted, formatting your hard disk, or causing an un-accounted for eclipse of the sun.
Note that compilers/linker are not requested to detect ODR violations.

  1. Are the static member s of two classes related because I get output as 7.

Maybe they are, maybe they are not. Really, undefined behavior might do just anything. What you see is just an artifact of however your compiler and linker are implemented.
A likely implementation will happily link all references to test::s to the same instance, but let each translation unit have - and link to - their own t object. (Since the class has only inline functions, the linker most likely never even sees anything of test except for test::s and those t instances.)

sbi
A: 

Unnice side-effect of how C++ actually works. Use namespaces to make the class names different to outside.

In past I had used the quite burdensome in practice rule: every library and file has to have a private namespace for to avoid such link conflicts. Or put the utility classes right into the main class definition. Anyway: not to pollute global namespace and most importantly ensure uniqueness of names across the whole project. (Writing that now I notice that I used pretty much verbatim the concept from Java.)

My search for equivalent of C's static in C++ was unfruitful...

Dummy00001
C++ has exactly the same concepts for static as C, plus some.
anon
@neil: How can I make a *static* method or class, which wouldn't be visible outside of the compilation unit? C has functions and data - applying *static* to them make them local. C++ has classes - but I haven't found anything to make a class local to the compilation unit.
Dummy00001
@Dummy Non-class static functions work _exactly_ the same in C++ as they do in C. The fact that you can't have compilation unit-local class-static functions (though you can of course have private ones) does not contradict my comment.
anon
@Neil. It does contradict to your "plus some" remark. The fact that C++ uses "static" keyword for other purposes doesn't change the fact that C++ doesn't provide all what C provides with its "static". In C one can have anything supported by language local to the compilation unit using "static" - in C++ can't, class methods have always linking-wise global scope. The original question spurs not from how C++ abuses the keyword, but how one can limit visibility of class implementation linker-wise to single compilation unit.
Dummy00001
@Dummy C++ has all the C static features **plus** class static and namespace local. I would say that is "plus some". This dialog is now closed from my side.
anon