why do " int ClassName :: VariableName " always needed to complete linkage? - c++

class X {
static int i;
// some other function, variable declaration, cons, dest
};
int X :: i ; **(!)**
Why must I write that (!) line, always ?
If I dont write, compiler cannot complete internal linkage, and so it gives ( I assume ) linker error. Why ?

This is known as the One Definition Rule. Each global object (technically, each object with external linkage) must be defined in exactly one source file (technically, in one translation unit). However, it can be declared as many times as you like.
Typically, a class definition will be in a header file, which might be included by many source files. So any static members can't be defined there, only declared, otherwise there will be multiple definitions. You must separately define the static members in exactly one source file, in order for the linker to find exactly one definition. That is what the line marked (!) does.

Because that is how static members work. They exist apart from the instances directly in the class.
You can't define them inside the class, because then you would have multiple definitions for every implementation file that is using your class.
Therefore you need to choose one implementation file that will actually define the static member.

The static variable must be defined (as opposed to declared) in a TU (i.e. a cpp file).
If it's only declared and not defined, no storage is allocated for it, so the linker can't find it.

static int i; is a declaration, i.e. tells to the compiler that in some translation unit (=>.cpp file) such static field will be actually defined. It is needed to let the compiler know that such variable exists and to let you use it in each translation unit where it's declared.
int X :: i;, instead, is a definition, it tells to the compiler to actually provide the space for that variable. It must stay in a single .cpp, otherwise each translation unit would provide some space for it on its own (and the linker would complain).
It's the exact same reason why for globals you need an extern declaration in every file that needs to use it (usually put in a header) and a normal definition in the single .cpp that defines it.

C++ makes a clear distinction between declaration and definition. You need to tell the compiler two things:
The data type of the variable: declaration.
The place in memory on where you want your variable to be located: definition.
This is usually done in one single step, ie a local int variable:
void f() {
int x; // Declaration and definition.
}
Since a .hpp header file can be included on many .cpp files, your (!) line must reside on a single specific .cpp, usually outside any header file.

Static class members are shared among all class instances (there is one and only place in memory where such variable resides) and therefore static int i; inside class declaration represents variable declaration only - and you need to allocate memory for that variable somewhere - you need to define it - which is done in implementation file with int X::i;

The class definition only defines the member, but it must exist in a single compilation unit (i.e. a .cpp file).
You could say it is part of the "one-definition rule".

Related

static const array initialized in the .cpp file

I have a problem with a part of old C++ code.
In the header file of the class myClass there is a static array member defined as follow:
static const int myArray[];
In the .cpp file it is initialized as follow:
const int myClass::myArray[]={2,4,5,7,9,11,13};
Is that allowed?
I don't care if it is not nice for the moment, I just want to know if it is going to give me weird problems..
Is that allowed?
To repeat #bolovs comment:
Yes, it's perfectly ok
I'm not fully sure what especially OP worried about.
So, I list the suspected issues the OP may have seen.
1. declaration in .h vs. definition in .cpp
That was the usual (and only) way to define static member variables in C++ – before static inline member variables were invented in C++17.
As a header might be included into more than one translation unit (aka. .cpp file), a definition in the header would be processed by the compiler multiple times and, hence, violate the One Definition Rule and usually result in a linker error.
2. declaration with empty brackets in .h
For the declaration, the actual size of the array is not necessary.
Please, note: static member variables does not contribute to the size of the class.
Hence, when the class is used in other translation units then the unknown size of the array is nothing that hinders the compiler to determine the correct size of the class.
3. definition with empty brackets in .cpp
This is an ancient feature which was inherited from C: An array may be defined leaving the size out when it can be determined from the initializer.
This is useful to eliminate redundancy from code.
(Otherwise, annoying bugs like const char text[10] = "Hello world."; may result because the author was not able to count correctly that "Hello world." requires 13 elements but not 10.)

C++ why we include all declarations in header files

#include <iostream>
When you do this and it becomes the source passing through the preprocessor, our file will be 5k. The compiler doesn't do all this declaration, right? (There are always some things we don't use after all)
| Is the linker or compiler preventing this?
**so when you include all declaration file in header **
improve build times.
link against code without having the source for the definitions.
avoid marking everything "inline".
compiler only see the declaration as it know definition might be somewhere , then it use all definition at the linking time.
The rule of thumb is this: Header files should contain declarations, source files should contain definitions.
Two types of Declarations:
DECLARATIONS: A declaration introduces a name into a scope. Generally speaking, a scope is either an entire .cpp file or anything in code delimited by {}, be it a function, a loop within a function, or even an arbitrarily placed block of {} within a function. A name introduced, is visible within the scope from the point at which it is declared to the end of that scope. A declarations merely tells the compiler how to use something, it does not actually create anything.
extern int y; // declares y, but does not define it. y is defined elsewhere,
// but the program can now use it since it knows what it is (an integer)
PROTOTYPES: A prototype is just another name for a declaration of a function.
double someFunction( double, int );
referred from :
http://www.cplusplus.com/articles/yAqpX9L8/
Also get more information on this site:
http://www.cplusplus.com/articles/Gw6AC542/

Why defining classes in header files works but not functions

I have this little piece of code :
File modA.h
#ifndef MODA
#define MODA
class CAdd {
public:
CAdd(int a, int b) : result_(a + b) { }
int getResult() const { return result_; }
private:
int result_;
};
/*
int add(int a, int b) {
return a + b;
}
*/
#end
File calc.cpp
#include "modA.h"
void doSomeCalc() {
//int r = add(1, 2);
int r = CAdd(1, 2).getResult();
}
File main.cpp
#include "modA.h"
int main() {
//int r = add(1, 2);
int r = CAdd(1, 2).getResult();
return 0;
}
If I understand well, we can't define a function in a header file and use it in different unit translations (unless the function is declared static). The macro MODA wouldn't be defined in each unit translation and thus the body guard wouldn't prevent the header from being copied in place of every #include "modA.h". This would cause the function to be defined at different places and the linker would complain about it. Is it correct ?
But then why is it possible to do so with a class and also with methods of a class. Why doesn't the linker complain about it ?
Isn't it a redefinition of a class ?
Thank you
When member functions are defined in the body of the class definition, they are inline by default. If you qualify the non-member functions inline in the .h file, it will work fine.
Without the inline qualifier, non-member functions defined in .h files are compiled in every .cpp file that the .h file is included in. That violates the following rule from the standard:
3.2 One definition rule
3 Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; ...
You will get the same error if you define member functions outside the body of the class definition in a .h file and did not add the inline qualifier explicitly.
Multiple translation units might need the definition of the class at compile time since it is not possible to know, for example, the types of members of the class (or even whether they exist) unless the definition of the class is available. (Therefore, you must be allowed to define a class in multiple translation units.) On the other hand, a translation unit only needs the declaration of a function because as long as it knows how to call the function, the compiler can leave the job of inserting the actual address of the function to the linker.
But this comes at a price: if a class is defined multiple times in a program, all the definitions must be identical, and if they're not, then you may get strange linker errors, or if the program links, it will probably segfault.
For functions you don't have this problem. If the function is defined multiple times, the linker will let you know. This is good, because it avoids accidentally defining multiple functions with the same name and signature in a given program. If you want to override this, you can declare the function inline. Then the same rule as that for classes applies: the function has to be defined in each translation unit in which it's used in a certain way (odr-used, to be precise) and all the definitions must be identical.
If a function is defined within a class definition, there's a special rule that it's implicitly inline. If this were not the case, then it would make it impossible to have multiple definitions of a class as long as there's at least one function defined in the class definition unless you went to the trouble of marking all such functions inline.
” If I understand well, we can't define a function in a header file and use it in different unit translations (unless the function is declared static)
That's incorrect. You can, and in the presented code CAdd::getResult is one such function.
In order to support general use of a header in multiple translation units, which gives multiple competing definitions of the function, it needs to be inline. A function defined in the class definition, like getResult, is automatically inline. A function defined outside the class definition needs to be explicitly declared inline.
In practical terms the inline specifier tells the linker to just arbitrarily select one of the definitions, if there are several.
There is unfortunately no simple syntax to do the same for data. That is, data can't just be declared as inline. However, there is an exemption for static data members of class templates, and also an inline function with extern linkage can contain static local variables, and so compilers are required to support effectively the same mechanism also for data.
An inline function has extern linkage by default. Since inline also serves as an optimization hint it's possible to have an inline static function. For the case of the default extern linkage, be aware that the standard then requires the function to be defined, identically, in every translation unit where it's used.
The part of the standard dealing with this is called the One Definition Rule, usually abbreviated as the ODR.
In C++11 the ODR is §3.2 “One definition rule”. Specifically, C++11 §3.2/3 specifies the requirement about definitions of an inline function in every relevant translation unit. This requirement is however repeated in C+11 §7.1.2/4 about “Function specifiers”.

Okay to declare static global variable in .h file?

static keyword keeps the scope of a global variable limited to that translation unit.
If I use static int x in a .h file and include that .h file every other file, won't they all belong to the same translation unit?
Then, won't x be visible everywhere?
So what is the role of static now?
Also, is there any use of static const int x ,where x is a global variable?
Aren't all const global variables static by default?
And is a const variable's scope limited to the TU even if it confined in a for loop in the file?
If you write
static const int x
in an .h file then every translation unit that #include-s this .h will have its own private variable x.
If you want to have 1 global variable visible to everyone you should write
extern const int x;
in the .h file and
const int x = ...;
in one of the .cpp files.
If you want to have a static const int visible to just one translation unit - don't mention it in the .h files at all.
If I use static int x in a .h file and include that .h file every
other file, won't they all belong to the same translation unit?
If you declare something as static (not inside a class, for class static keyword has a different semantic), that static variable cannot be seen outside its TU. So putting it in the header file will cause each TU including that header to have a different private copy of that static variable.
And is a const variable's scope limited to the TU even if it confined
in a for loop in the file?
NO. Even for a static const value, the scope is determined by it's declaration. So the scope will be limited by your for brackets.
you will end up will private copies of that variable per translation, which will result in bloat if you put it there. it would also make no sense to have to random copies all over the place. no it's not ok.
you can declare a const int in a namespace block; that's ok.
The observable difference for variables that are const qualified is that in the static version you will get one copy per translation unit and so address comparisons of two such copies may fail.
If you never use the address of your const variable any modern compiler should be able to just use the value and optimize the variable itself out. In such a case a static const-qualified variable is completely fine.
Basically, each source file together with all included header files is a single translation unit. So If you have a static variable in a header file then it will be unique in each source file (translation unit) the header file is included in.
"static global" doesn't make sense, they are in a way each other's opposites.
The term "global" is often misused to describe a variable declared outside any function at file scope. But rather, a global variable is one with external linkage, that can be accessed by any file in the project - hence global.
The opposite of external linkage is internal linkage, which means that a variable can only get accessed by the translation unit where it is declared. Translation unit meaning one .c file and all the headers included by it (recursively).
static is a guarantee that a variable gets internal linkage. Thus other translation will not be able to access it or declare extern variables referring to it.
What happens if you declare a static variable in a header file is that more than one translation unit will get a separate variable with that name. The code will compile fine, although clever linkers will notice this and give a linker error. These kind of linker errors are often non-descriptive and hard to track down.
This leads us to the following best practices:
Never declare any variables inside a header file, as this often creates subtle bugs and linker errors.
To prevent such bugs, always surround all header files with "header guards":
#ifndef MYHEADER_H
#define MYHEADER_H
/* contents of header */
#endif
All variables declared at file scope should be declared static, for the purpose of private encapsulation and to reduce namespace clutter. Similarly, extern should be avoided, as it leads to bad design and spaghetti programming.

extern pointer problem in c++

I have a header file that has a number of declarations like this:
extern ID3D10Device* device;
I can't make these static because of a problem with multiple translation units, and I can't have them as normal pointers for a similar reason. However when I try to build the program I get unresolved external symbol linker errors. I'm assuming that this is because I'm attempting to use the pointers without defining them first. This is the problem however, as the way you initialise these DirectX objects is by passing the address of the pointers as parameters into specialist methods. - I may be wrong but I am assuming this is the problem as the compiler / linker / whatever can't see the definitions.
All I'm trying to do is have these pointers (for the graphics device, depth buffer etc) visible to multiple classes. How can this be achieved?
You need the pointers to be defined in some translation unit. The linker is complaining because it seems you haven't done that anywhere. You should declare them at file scope as
ID3D10Device* device = NULL;
in the source file where you call the DirectX function that initializes them. Just make sure the declaration is only made in one source file, then the extern statement should be placed in the associated header file which is included by all translation units that need to use these pointers.
When you externally define a variable like this, the compiler is not reserving any memory for that variable until it sees a definition inside a code module itself. So if you are going to be passing these pointers by-reference to a function for initializing their values, they must be defined in a code module somewhere.
You only need to define them in a single code module ... then place the extern declarations inside a header file you include in the rest of your code modules that require access to the pointer variables. That shouldn't create any linker errors due to duplicate definitions.
I can't make these static because of a problem with multiple translation units
If you need a different variable in different TU (translation units), make it static: this way the variable will be specific to each TU.
A declaration of a variable is also definition unless the extern is used.
You must have one (and only one) definition of a variable in the program.
To have a global variable:
Declare it with the extern keyword in some header file.
Include this header in every TU that needs to use the variable. Never declare the variable directly, never bypass the header inclusion.
Define the variable: a declaration without the extern keyword will define the variable in one TU. You need to include the header file in the same TU to guaranty consistency between the extern declaration and the definition.
the way you initialise these DirectX objects is by passing the address
of the pointers as parameters into specialist methods
To solve this part of the problem, you could do something like this (in a .cpp file):
ID3D10Device* device;
struct Foo {
Foo(ID3D10Device **pdevice) { specialist_method(pdevice); }
};
Foo f(&device);
Beware of the "static initialization order fiasco", though -- it's safe to use device from main, or code called from main, because it will definitely be initialized before that code executes. It's not necessarily safe to use it from other initializers executed before main, because the order of initialization of statics in different translation units is unspecified (within a TU, they're initialized in order of either declaration or definition, I forget which). So device might still be a null pointer in that code. Likewise, specialist_method can't necessarily rely on other statics having been initialized.
There are extra tricks you can use if you need to enforce initialization orders, I'd guess that all the common ones are on SO already in other questions.