There are sources (books, online materials) that explain the usage of extern
as following:
extern int i; // declaration - has 'extern'
int i = 1; // definition - specified by the absence of 'extern'
And there are sources that support the following syntax:
extern int i; // declaration
extern int i = 1; // definition - specified by the equal sign
// Both marked with 'extern'
My question is - is this a C vs. C++ distinction, or is it a pre-ANSI vs. ANSI practice?
Now, the more practical question:
Using the second syntax, I want to create a global object (visible from every compilation unit). The constructor takes no parameters, so neither parentheses, nor the equal sign are necessary.
extern MyClass myobject;
Now how can the compiler make the distinction between a declaration and the definition?
EDIT: Back at school, I was used to the first syntax (Borland C). Later I used a compiler (probably some ancient version of GCC) that refused to compile a definition without an 'extern'. That is what made me confused.
Specifically for your examples, there's no distinction between C and C++ at work here. The basic rule that works in both languages is this: if your declaration includes an initializer, then it is a definition. Period. It does not matter, whether it has explicit extern
in it or not. If it has an initializer, then it is a definition.
That means that in namespace scope both extern int i = 1
and int i = 1
are equivalent, i.e. extern
in such declaration is redundant. In C++ extern
in definitions becomes non-redundant when the declared object is const
, since const
objects in C++ have internal linkage by default. For example, extern const int c = 42;
defines constant c
with external linkage.
If a declaration has no initializer, then (and only then) it begins to depend on the presence of extern
keyword. With extern
it is a non-defining declaration. Without extern
it is a definition. (In C it would be a tentative definition, but that's beside the point in our context).
Now, for your practical question. In order to create a global object, you have to declare it as
extern MyClass myobject;
(which will usually be done in a header file), and then define it in some translation unit as
MyClass myobject;
Since your constructor takes no arguments, this is the only way to define your object. (Starting from C++11 you can also use MyClass myobject{};
if you so desire.)
If you had to supply arguments to the constructor (say, 42
), you would be able to use both
MyClass myobject(42);
and
extern MyClass myobject(42);
as definition, since presence of an initializer ensures that it is indeed interpreted as a definition.