Proper use of header in C++ - c++

I am playing around with multiple files in C++, and I have come of with the following example with does not compile:
main.cpp
#include <iostream>
#include "const.hpp"
using namespace std;
int main()
{
extern double var;
var = 5;
cout << var << endl;
return 0;
}
fct.cpp
#include <iostream>
#include "const.hpp"
using namespace std;
void func()
{
extern double var;
cout << var << endl;
}
const.hpp
#ifndef CONST_H
#define CONST_H
double var;
#endif
My program does not compile, because apparently there is a multi-definition of var. Am I correct to assume that, based on this example, a header file is not intended to be used for declaring variables as in my example above?
Instead, the correct procedure is to declare all variables in a .cpp file and use a header to tell each (relevant) translation unit that the .cpp file contains an external (extern) variable?
EDIT: Is it correct that an exeption to my rule above is when dealing with constant variables (const), which should be defined in a header?

double var; is a definition - including that header in multiple files will violate the one definition rule. If you want a global (think twice) you'll have to declare it in the header - extern double var; and move the definition to a single implementation file.

Am I correct to assume that, based on this example, a header file is not intended to be used for declaring variables as in my example above?
A header file is intended for declaring variables, but your header file defines a global variable with external linkage, and it is imported multiple times. The linker then reasonably complains about multiply defined symbols.
Instead, the correct procedure is to declare all variables in a .cpp file and use a header to tell each (relevant) translation unit that the .cpp file contains an external (extern) variable?
Yes, except that you would not be declaring the global variables in that .cpp file, but rather providing a definition for them.
const.hpp
#ifndef CONST_H
#define CONST_H
// ...
extern double var;
// ^^^^^^
#endif
globals.cpp (could be any other .cpp file, as long as it is only one)
// ...
double var;
Also, if you are wondering about the reason why your include guards won't protect you in this case, this may help you .
Is it correct that an exception to my rule above is when dealing with constant variables (const), which should be defined in a header?
In a sense, yes. Global variables qualified as const have internal linkage by default, which means that each translation unit will receive a private copy of that variable. So even when the variable's definition is included by multiple translation unit, the linker will not complain about multiply defined symbols.

Related

Correct way of initializing a class globally in C++

I know global is bad but just as a practice, is this the correct way to initialize a global class used between multiple object files?
Header 1.h
class test {
int id;
public:
test(int in){
id = in;
}
int getId(){
return id;
}
};
extern test t;
File 1.cc:
#include <iostream>
#include "1.h"
int main(){
std::cout << t.getId() << std::endl;
return 0;
}
File 2.cc:
#include "1.h"
test t(5);
Now what if instead of extern I use the static approach globally static test t(0); in the header?
Correct me if I'm wrong but that would compile fine however I would have 2 different unrelated copies of the same t in both object files and the final binary? Is that bad? Or does the linker sort it out to eliminate multiple copies?
There are global instances, not global classes.
What you have is a global instance. And yes, this sounds about right, until you get to multiple global instances which depend upon each other. Then the real fun will start.
Defining a variable as 'static' at global level means the variable will be defined in the compilation unit only (i.e. the '.o' file) and the symbol won't be exported by the compiler.
In other words: yes, there will be multiple variables with the same name but only visible to functions on the same compilation unit.
Besides, 'invisible' doesn't mean 'inaccessible'. You still can provide access to the variable. For example:
1.h
struct Test { int value; }; // Class definition
Test& get_t(); // Function declaration
1.cc
#include "1.h"
static Test t; // Variable declared as 'static'
Test& get_t() { return t; };
2.cc
#include "1.h"
#include <iostream>
int main()
{
std::cout << get_t().value << std::endl; // Static variable accessed
}
I use the static approach globally static test t;?
But your test class needs an int in parameter for the constructor, so you want:
static test t(0); // or whatever int you want
If you turn the extern to static in the header, you would define a static variable in each compilation unit in which the header is imported. So classes in different cpp files would no longer "communicate" via t, since each would have theirs. This is very error prone.
In addition, adding the definition of a static in a header is an extremely bad practice. When someone includes a header, one does not expect that it will create variables.
Including the declaration of t as extern is an acceptable practice. But be aware that if the header has a general purpose, this might reduce its reusability other projects.
More information of interest for you:
Must read: C++ Core Guidelines about source files
Must read: Guidelines for writing headers
StackOverflow: When are global variables recommended
Why global variables should be avoided if possible and when are they ok
If you put a variable declaration outside of any function, you're declaring the variable as 'global'. Ex:
1.cc
int this_is_global;
From here on you can use the variable in any function of '1.cc'.
For using the same variable in any other file, the compiler will need to know about it:
2.cc
extern int this_is_global;
Here, the keyword extern tells the compiler that the variable is declare somewhere else, letting the task of finding it to the linker.
If you miss to add the extern keyword here, the compiler will treat it as a new variable, and the linker will have two variables with the same name and will emit an error. All of your source files of your project except the first one will need the extern keyword to avoid duplicate symbols.
So common practice is to add the 'extern' declaration in an include file:
1.cc
int this_is_global;
1.h
extern int this_is_global;
2.cc
#include "1.h"
On the other side, the static keyword tells the compiler not to export the symbol. In other words: the variable will exists only in the source file it is declared. You could declare it once per source file and there will be different variables with the same name. Ex:
1.h
static int my_var;
1.cc
#include "1.h"
2.cc
#include "1.h"
This way, you'll end having two variables 'my_var' and changes to any of them won't affect the other.

How C++ differentiates between a call to global variable and declaration of a global variable?

This is the most confusing part for me from section Global Variables and linkage properties.
extern int g_var1;
Statement could be something like this when defining an external non-const global variable. I think I will write exactly the same for using that variable (through forward-declaration) in some other file. If both the statements are same, how C++ knows whether the variable was declared or was defined in a file?
If I understand your question correctly, you shouldn't write exactly the same in another file (namely, you shouldn't write "extern int g_var1" in two files). A good practice is to declare some variable global in a header file; make the definition in a cpp file that includes this header file. After doing this, you can use this variable in all of the files that will include the header file.
To illustrate, an example would be something like this:
variables.hpp
#pragma once
extern int g_var1;
variables.cpp
#include "variables.h"
int g_var1 = 1;
main.cpp
#include "variables.h"
#include <iostream>
using namespace std;
int main(){
cout << g_var1 << endl;
}
A statement of the form
extern int g_var1; // this is a declaration
is a declaration of a variable. The keyword extern makes sure of this.
If you write
int g_var1; // declare and define variable
you define it as well. You can declare a variable as many times as you like, but define it only once. You could therefore write
extern int g_var1;
in those files where you need to use the variable. Then during linking the compiler will resolve the definition of the variable (provided that you give the definition in some file of course).
When you say extern int g_var1; the variable is just declared, and later when you have to use it you can use it directly.
file1.cpp:
int g_var1;
File2.cpp:
extern int g_var1;
You need not to write extern everytime.
Though i would suggest if you have to use global variables place them in a separate header file.

creating global variables causes linker error

I have an MFC application AVT_testapp, and in the header file (AVT_testappDlg.h) I am trying to create a variable outside of all functions, classes, etc. in order to make it global. Whenever I try to do this though (say I try int x = 7), I get the error:
1>AVT_testappDlg.obj : error LNK2005: "int x" (?x##3HA) already defined in
AVT_testapp.obj
1>..\..\bin\x64\Debug\AVT_testapp.exe : fatal error LNK1169: one or more
multiply defined symbols found
Everything I have found on google says "just add header guards". AVT_testappDlg has 6 #include's, and each of them has header guards.
What else could be causing these errors when creating global variables?
EDIT: Here is the beginning of my header file,
#pragma once
#include "../../src/CoreUtils/nierr.h"
#include "..\..\src\CoreUtils\StringHelpers.h" //includes windows.h
#include "afxwin.h"
#include "afxcmn.h"
#include "IFrameObserver.h"
#include "c:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include\GdiPlusHeaders.h"
//#include <fstream>
//#include <windows.h>
int x = 7;
using namespace AVT::VmbAPI;
//////////////////////////////////////////////////////////////////////////
////////// MyObserver class ///////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
class MyObserver : public IFrameObserver
{
private:
MyObserver( MyObserver& );
MyObserver& operator=( const MyObserver& );
public:
VmbUchar_t* imageData;
//...
//...
//...
//...
//that's the end of the relevant stuff
You cannot define variables at namespace level in a header. In general it is best not to have global variables, but if you need to you should provide only a declaration in the header and the definition in a single .cpp:
//header
extern int i;
//cpp
int i;
The problem with your code is not related to header guards. Header guards ensure that a header is parsed only once in each translation unit. Lack of header guards causes compiler errors, where the compiler sees, say for example a class, defined multiple times in the same translation unit after preprocessing. In your case the error is a linker error LNK2005, and it means that the same symbol was defined in multiple translation units (in your case in each translation unit that includes the header with the definition).
If the global variable is not const(*), you cannot put it in a header file and include it in multiple translation units (i.e. .cpp files). Otherwise, you will end up with multiple definitions of the same symbol in your program, violating the ODR (One Definition Rule, see Paragraph 3.2 of the C++11 Standard), and the linker will complain about that.
You should use the extern modifier in your shared header to provide only a declaration of your variable:
extern int var;
Then, in one single .cpp file, you can provide a definition for it:
int var;
(*) const global variables have internal linkage by default, so each translation unit will end up having a private copy of it and no multiple definition will occur.
if you insist on having a global variable at least put it in a namespace to avoid collisions with other modules
namespace globals
{
extern int x;
}
then in the .cpp file define it.
int globals::x = 0;
it also makes it more clear that it is a global variable.

include header file error: multiple definition

I have a very simple file system in a program.
There is :main.cpp which include worker.h, worker.h and worker.cpp which include worker.h
worker.h has the Header guard and has some variables declared which are required by both main.cpp and worker.cpp and it has some function declarations.
#ifndef __WORKER_H_INCLUDED__
#define __WORKER_H_INCLUDED__
bool x;
int y;
void somefunction( int w, int e );
#endif
Going through some other threads and google results, I understood that the Header guard protects you from multiple inclusions in a single source file, not from multiple source files.
So I can expect linker errors.
My question is
Why there are multiple definition errors for only variables and not for functions ? As far as my understanding goes both of those are only declared and not defined in the header file worker.h
How can I make the a variable available to both main.cpp and worker.cpp without the multiple definition linker error ?
Why there are multiple definition errors for only variables and not for functions ? As far as my understanding goes both of those are only declared and not defined in the header file worker.h
Because you defined the variables. This way they are only declared :
extern bool x;
extern int y;
But you have to define them in a cpp file. :
bool x = true;
int y = 42;
An updated answer for c++17. With the introduction of inline variables, one no longer needs to worry about the exact translation unit where non-const namespace scoped variables need to be placed. Putting aside the discussion about use of global variables in general, another way to fix the OP in modern C++ is to declare the variables as follows:
inline bool x; // Can add an initializer here too
inline int y;
So long as this is in a header and all TU's see the same exact definition, the implementation will resolve it and make sure those TU's all refer to the exact same unique object.

Can I include global static member?

There are few global variables which are static in one of the header files. I see these variables are used in the associated .cc files. So, looks like this has no issues.
My questions are:
Whats the difference between including a global variable vs static global variable ?
I know static global doesnt have visibility outside its file. But dont know how this would work when it comes as part of a .h which is #included.
I wrote a sample program, and tried the same thing. But, I get compilation error the moment I make the variable static. When it is just global, it is fine.
So, is there something which I am missing on a regular g++ build ? (Please note, the initial case was on our official code base which has enough makefiles, .h files and all).
Thanks for the help !
Here is my sample program :
.h file:
#include <iostream>
typedef unsigned int uint;
static const int appk=189;
class abc1
{
public:
abc1(int x);
virtual void printVal();
};
.cc file:
#include "abc1.h"
extern int appk;
abc1::abc1(int x)
{
}
void abc1::printVal()
{
printf("abc1 print: %d\n", appk);
}
(1) If you put a global variable in a .h file and include it in various .cpp/.cc files then it will be defined multiple times for every file. So you are most like to get a linker error.
To overcome that, mostly you are likely to use extern keyword:
// myfile.h
extern int i;
and define that in only one translation unit:
// somefile.cc
int i;
(2) If you put a static global in a .h file and include it, then you will not get any error, because for every different translation unit, there will be a different copy for that static global variable.
// myfile.h
static int i; // creates a unique and unrelated copy in all .cc file where included
However, such usage is deprecated; instead of that it's better to use unnamed namespace:
namespace {
int i;
}
From your question, I don't see that you should get any linker error for static global.
Hard to tell your compilation error without code, but if you have a header that declares a static global, then you just create that global variable independently and separately in each translation unit that includes the header.
Example:
header.h:
#ifndef H_XXX
#define H_XXX
static int a;
#endif
file1.cpp:
#include "header.h"
// now have access to a variable called "a"
file2.cpp:
#include "header.h"
// now also have access to some "a"
The two files both have access to a global variable called a, but each file has its own separate copy, private to its translation unit, which is not visible outside.
For a practical example, I think cout is declared as a static global, so everyone who uses <iostream> gets their own copy.
static variable has internal-linkage. What it means is that if you have a static variable a in x.h and you include x.h in two files say m.cpp and n.pp then each of these two files gets its own copy of a which means if you change its value in m.cpp, then n.cpp is not going to see that change, because there exists two variables with same name in each translation unit (.cpp). And they're independent of each other.
But if a is not static, then including x.h in more than one files, you will get multiple-definition error, because each inclusion of x.h will try to define a, but since a is not static; it has external linkage now, which means if its defined in m.cpp, then you will get error when including x.h in n.cpp (or vice-versa). In this case, you've to write x.h as:
//x.h
extern int a;
And then define a in exactly one .cpp file, either m.cpp or n.cpp, but not both. Say its m.cpp.
//m.cpp
#include "x.h"
int a =10;
And you're done. Now you can include x.h in as many .cpp file as you want, and can access a, modify its value, do whatever you want. Any change to it, will be seen by all .cpp files now.