tags:

views:

729

answers:

4

Failed to link up following two files, when I remove the "static" keyword, then it is okay. Tested with g++. Check with readelf for the object file, the static member seems is exported as a global object symbol... I think it should be a local object ...?

static1.cpp

class StaticClass
{
public:

    void    setMemberA(int m)   { a = m;    }   
    int     getMemberA() const  { return a; }

private:
    static  int     a;  

};
int StaticClass::a = 0;
void first()
{
    StaticClass statc1;
    static1.setMemberA(2);
}

static2.cpp

class StaticClass
{
public:

    void    setMemberA(int m)   { a = m;    }   
    int     getMemberA() const  { return a; }

private:
    static  int     a;  

};
int StaticClass::a = 0;
void second()
{
    StaticClass statc1;
    static1.setMemberA(2);
}

With error info:

/tmp/ccIdHsDm.o:(.bss+0x0): multiple definition of `StaticClass::a'

A: 

StaticClass needs a place to store a, a static variable that will be shared by all class instances - there are two lines that do so, one in each file. Removing one will fix the linker error.

fbrereto
+5  A: 

The following is a definition of the static data member. It has to occur only in one file that's compiled and then linked.

int StaticClass::a = 0;

If you have multiple such definitions, it is as if you had multiple functions called first. They will clash and the linker will complain.

I think you are mistaking static members with static applied to namespace scope variables. At the namespace level, static gives the variable or reference internal linkage. But at the class scope level (when applied to a member), it will become a static member - one that is bound to the class instead of each object separately. That then has nothing to do with the C meaning of "static" anymore.

Johannes Schaub - litb
The problem is that I think the linker should know it link the variable in its local object file, since this is a local static variable, not a global static one.
arsane
it's neither local nor global. it's a class member. http://en.wikipedia.org/wiki/Class_variable
Johannes Schaub - litb
@arsane, If you want a locale class, you have to put it in an anonymous namespace. As you write it, StaticClass from static1.cpp is the same class as StaticClass from static2.cpp. Before saying that the classes aren't defined in an header, don't forget that the macropreprocessor work by textual inclusion.
AProgrammer
@arsane, you may access the static member from any other object file code, and it will link together properly. @AProgrammer, ah good point. Maybe that's what causes the confusion.
Johannes Schaub - litb
A: 

The statement

int StaticClass::a = 0;

actually allocates storage for the variable, this is why it should be only written once.

As for your remark, you are probably confusing two different uses of the static keyword. In C static used to mean "use internal linkage", this means that the name of a variable or function would not be seen outside the translation unit where it was defined.

In classes, static is used to define class members, that is variables or methods that don't refer to a specific instance of the class. In this case the storage for a static variable must be allocated somewhere (as it is not part of any instance), but only in one place of course.

UncleZeiv
+5  A: 

It seems like you're trying to have local classes in each source file, with the same name. In C++ you can encapsulate local classes in an anonymous namespace:

namespace {
class StaticClass
{
public:

    void    setMemberA(int m)   { a = m;    }   
    int     getMemberA() const  { return a; }

private:
    static  int     a;  

};
int StaticClass::a = 0;
} // close namespace

void first()
{
    StaticClass statc1;
    static1.setMemberA(2);
}
Ropez
@Ropez: it works well. Thanks :)
arsane
I feel bad with the state of affairs, since ropez' answer seems to have given you the solution you were looking for. feel free to move the check-mark to his one :) +1 for him, anyway.
Johannes Schaub - litb
@Litb, both of you are right :) you explained more.
arsane