3

This code will produce error in c++

// Foo.cpp
const int Foo = 99;

// Main.cpp
extern const int Foo;
int main()
{
    cout << Foo << endl;
    return 0;
}    

Reason as given by many is global const has internal scope and it is default static.

solution to this is :-

    //Foo.h
    extern const int Foo; 

    // Foo.cpp
    #include "Foo.h"
    const int Foo = 99; 

    // Main.cpp
    #include "Foo.h"
    int main()
    {
       cout << Foo << endl;
    }

I used to think that extern is used to tell compiler that memory for the indentifer is already allocated somewhere in other files.
Applying same logic on above code can anyone explain what is happening here or extern has different meaning in c++??
enter link description here
Also consider this page it is spoiling my all intuitions..

T.J.
  • 1,466
  • 3
  • 19
  • 35

2 Answers2

9

What if we have to declare only a global constant(not static)? How extern help in doing this?

A const object declared with extern qualifier has external linkage.
So if you want to use a const across multiple Translation units, add an extern qualifier to it.

While a global variable has external linkage by default,why a const global has internal linkage by default?

Reference:
C++03 Standard Annex C Compatibility C.1.2 Clause 3: basic concepts

Change: A name of file scope that is explicitly declared const, and not explicitly declared extern, has internal linkage, while in C it would have external linkage

Rationale: Because const objects can be used as compile-time values in C + +, this feature urges programmers to provide explicit initializer values for each const. This feature allows the user to put const objects in header files that are included in many compilation units.


Avoid the confusion by following a simple rule:

By default Linkage is external for non-const symbols and static (internal) for const symbols.

Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533
3

A quick reminder, so that it is clear what we are talking about:

int const a;            //  illegal
int const a = 42;       //  definition, internal linkage
extern int const a;         //  declaration, external linkage
extern int const a = 42;    //  definition , external linkage

Note that without the const, the first two declarations above are both definitions with external linkage. This is anything but orthogonal, and not very intuitive, but this is what the current rules say.

The problem with giving a const external linkage is that there can be only one definition of an object with external linkage, and with one exception, only the definition can have an initializer. This means that for a const with external linkage, the actual value (necessary if the const is to be used in a constant expression) can only be visible in one translation unit. This is probably the motivation for giving const internal linkage by default.

Of course, this causes no end of problems with templates, at least theoretically; the following header has undefined behavior if it is including in more than one translation unit:

#include <std::vector>

int const fixedValue = 42;
inline void insertFixedValue( std::vector<int>& dest )
{
    dest.push_back( fixedValue );
}

The standard says that not only must inline functions and templates have an identical sequence of tokens, but that all of the symbols must bind to the same object in every translation unit, or there is a violation of the one definition rule. And since fixedValue does not have external linkage, there is a unique instance in each translation unit. (There is an exception if the symbol refers to a const object and there is an immediate lvalue to rvalue conversion. Since std::vector<int>::push_back takes its argument by reference, however, there is no immediate lvalue to rvalue conversion, and we get undefined behavior.)

And of course, anyone with a template:

template <int& r> ...

cannot instantiate it with fixedValue either.

The reason for the internal linkage is, of course, historical. Today, compilers must be able to support things like:

struct X
{
    static int const a = 42;    //  declaration!!!, external linkage
};

and all sorts of duplicate definitions for functions. It would be relatively trivial to extend the rules allowing initializers on a declaration in a class to variables at namespace scope, to give something like:

int const a;                //  illegal
int const a = 42;           //  definition, external linkage
extern int const a;         //  declaration, external linkage
extern int const a = 42;    //  declaration, external linkage

This would restore orthogonality (even if it required extra typing). it would also break almost all existing code.

Another alternative would be to treat const variable definitions exactly as function templates are treated today: you can have multiple definitions, but they must all be identical. This would probably avoid most, if not all, code breakage.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • `extern const a; ` is not valid C++, I don't think. You need something like `extern const ` **int** `a;` You have it wrong in your first highlighted block, but correct in the last. – Robert Crovella Aug 06 '14 at 19:25
  • @RobertCrovella I don't think it's even valid C, today (and it is certainly bad practice if it is valid). I've fixed it. – James Kanze Aug 07 '14 at 08:23