//a.h
extern int x1;
static int x2;
int x3;
static const int x4;
class A {
public:
static const int x5 = 10;
};
a.h
will be included by multiple .cpp
files, my question is:
1.x1
is just a declaration, isn't it? So its definition should be done in one of those .cpp
files, right?
2.x2
is a definition, right? I used to think that static int
is also a declaration just like extern int
, but I was wrong. x2
will only be visible in a.h
?
3.x3
will be defined multiple times if a.h
is included in multiple .cpp
files, so x3
will result in compile-error, right?
4.x4
is a definition, right?
5.Here in class A, x5
is a declaration, yes. But what about x4
?
1.x1 is just a declaration, isn't it? So its definition should be done in one of those .cpp files, right?
Correct
2.x2 is a definition, right? I used to think that static int is also a declaration just like extern int, but I was wrong. x2 will only be visible in a.h?
A different x2
will be available in each translation unit that includes the header.
3.x3 will be defined multiple times if a.h is included in multiple .cpp files, so x3 will result in compile-error, right?
More precisely it will result in a linker error. The compiler processes each translation unit, the linker binds them together and detects that the symbol is defined multiple times.
4.x4 is a definition, right?
Yes, it is a definition, but as with x2
each translation unit will have it's own x4
(both because of static
and because it is const
which implies internal linkage
5.Here in class A, x5 is a declaration, yes. But what about x4?
Yes, x5
is a declaration only (with initialization). The confusion might arise because the keyword static
is reused to mean different things in different contexts. In x5
it means attribute of the class, while in x4
it means internal linkage
This last case is special. It is the only declaration (IIRC) where the declaration can have a value, and the reason is that it allows the compiler to use the value of the constant in all translation units that include that header as a compile time constant. If the value had to be provided with the definition, then only a single translation unit would have access to that value. The definition of that static member would be:
const int A::x5; // no initialization here
And you must provide one if the member is odr-used. Now the fact is that in most cases the constant will not be odr-used as the compiler will substitute the value when the expression A::x5
is used. Only when the member is used as an lvalue you need the definition, for example:
void f( const int & ) {}
int main() {
f( A::x5 );
}
Because the argument to f
is a reference, the use of A::x5
requires an lvalue (note, const-ness and lvalue/rvalue-ness are almost orthogonal), and that requires the definition of the member in a single translation unit in your program.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With