开发者

static initialization confusion

开发者 https://www.devze.com 2023-01-03 04:16 出处:网络
I am getting very confused in some concepts in c++. For ex: I have following two files //file1.cpp class test

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.


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?


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.


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.


  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.)


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...

0

精彩评论

暂无评论...
验证码 换一张
取 消