tags:

views:

103

answers:

3

Here is my code -

#include <iostream>
#include <conio.h>

using namespace std;

class Base
{
public:
int a;

};

//int Base::a = 5;

class Derived : public Base
{

public:
int static a;
};

int main()
{
   Derived d;
   cout<<d.a;
   getch();
   return 0;
}

I get a linker error here. But when I do it the other way round -

class Base
{
public:
int static a;

};

int Base::a = 5;

class Derived : public Base
{

public:
int a;
};

I get no error. Can someone please explain what is happening here.

+6  A: 

All static members have to be explicitly defined/initialized outside the class.

In the second example you do this correctly (int Base::a=5), but in the first example you don't do this for Derived::a, adding the following line to the first example should solve it:

int Derived::a = 5;
Patrick
@Patrick: Yes it solves the error but why doesnt the compiler give an error for multiple declarations of variable a? Is promotion/demotion from/to static allowed while inheriting?
Bruce
Derived::a simply overrules Base::a, just like defining a variable i in a code-block overrides a same-named variable outside the block. This is perfectly legal. Consider using static-code-analysis tools (like PCLint) to find this kind of hard-to-find problems.
Patrick
@Patrick: Just out of curiosity...is this allowed in Java?
Bruce
@Bruce: Multiple declarations will happen if you defined them in the same class. In this case, you actually defined them in the base class and then in derived class. So, your Base::a became hidden because of the Derived::a.
jasonline
In Java it is allowed, the only difference is in the behavior if `a` is static in `Derived`. In C++ the syntax `Derived d; d.a;` is a valid syntax for accessing a static attribute of `Derived`, and the value will be that of `Derived::a`. In Java, on the other hand, `d.a` will always give you the member attribute (which in this case is defined in `Base`). If the `a` is static in `Base` and non-static in `Derived` the behavior will be the same.
David Rodríguez - dribeas
+2  A: 

You need to actually define static members. The same way as you do

int Base::a = 5

in the second case you should have done

int Derived::a = 5;

in the first case.

sharptooth
+1  A: 

There are two questions here. The first is why do you get the linker error in the first example? Well, you get a linker error in the first example because you have not defined/initialized the static member of class B.

The second question is why does the compiler not complain of multiple declarations? The compiler does not complain of multiple declarations because as far as it is concerned, the two variables are in different scopes and their mangled names will be different anyway. This has got nothing to do with one of the variables being static. In fact, static members are not even inherited. SO, the following code snippet without static variables is also correct:

class B {
public:
int a;
};

class C: public B {
public:
int a;
};
Rajorshi