I'm writing a library which is totally base on templates, so I don't have any cpp files. Now I want to declare an global variable, then I realize I have nowhere to go.
If I simply declared it in header, I will got a "multiple definition" error, if I use extern, I have to create a cpp file to really declare it.
So is there any way I can declare a global variable in header?
P.S. since a static member in a template class can (only) be declared in header, how it works?
You can use macro to for single declaration,
#ifndef __usermacro
#define __usermacro
//Declare global variable
#else
//Declare extern
#endif
As #M.M mentioned, you can use inline declaration if you're on C++17 or above.
Hovever, if that's not the case, you can declare inline function which returns a reference to static variable, just like that:
inline int& getData() {
static int data;
return data;
}
Then, in your .cpp file (as well as in any function body inside your headers) you can simply call it like int& data = getData().
As a side note, if you want to ensure that global object is created only once and is not copied by accident, it could suit you better to use a signleton instead. Global variables are more of a c-style and not really considered a good practice in c++.
Related
It's incredible. Over 30 years I've been programming and I seem to have forgotten how to handle global variables. (It's because I never really use them I guess.) In the header file I have -
// any.h
bool neat;
and in the cpp -
// any.cpp
#include <any.h>
bool neat = false;
it told me I was redefining. So I took out the 'bool' -
// any.cpp
#include <any.h>
neat = false;
Now it tells me "error: ‘neat’ does not name a type"
How can it not know 'neat' is a bool? It's the same translation unit
so I don't need an extern. I haven't declared anything static
so I know there is no limitation to file scope. This is supposed to be
a global variable.
My understanding of the difference between declaring and defining is
that with 'declaring' you are just informing the compiler a name is
of a certain type. Whereas with 'defining' the compiler actually sets
aside some space in the executable for the name to exist.
What am I doing wrong?
You need to use the extern keyword in your header file (and keep the bool in your .c file)
// any.h
extern bool neat;
// any.cpp
#include <any.h>
bool neat = false;
The reason to do that is to let the linker know there is a variable of that name anywhere in any object, but not reserve memory for it in every object using that variable. However, in the object actually defining the variable, you have to define it as you would do it for a non exported variable.
Note that bool neat; (and bool neat = false;) is a definition; That means if you put them both in the header file and implementatioin file, you'll get multiple definition error.
You could use extern to change it a declaration,
In addition, a variable declaration that uses extern and has no initializer is not a definition.
e.g. you can declare them in header file as
extern bool neat; // declaratioin
and define them in implementation file as
bool neat; // definition
// or bool neat = false; same effect here
About the error of the 2nd code snippet, note neat = false; is not declaration nor definition; it's a statement (assignment), which must be put in a function. e.g.
// any.h
bool neat; // definition
// any.cpp
#include <any.h>
void init_neat() {
neat = false;
}
int main() {
init_neat();
// use neat ...
}
In a comment, you said:
Do you mean as functions within a class (or namespace)? Or do you mean as global functions? And if so, how is that better to have two global names (setNeat and getNeat) instead of one (neat) ?
It is less important whether the function is in a namespace or it is a global function. IMO, it is better to provide access to the data through a function than accessing it through a global variable.
You have various options in the implementation of the functions.
You can use a variable to maintain the state.
You can pass the function call to another function whose implementation maintains the state.
You can use an aggregate object, like a struct, to maintain many other global states of the application.
You give yourself the option of being able to change how and where the data is maintained when you provide access to it through a function.
What if I declare a class variable as extern so that it can access some global variable declared in some other file? Does such a scenario come up anytime or is it just a hypothetical case?
Lets say I have a header file global.h
extern int myglobalint;
and I have a cpp file my.cpp
Here I declare a class A
class A{
//use that variable here....is it possible
}
Yes it comes up from time to time, particularly in messy code. :D
Perhaps a more C++-like style would be to keep these kinds of variables together in a class, eg in global.h:
class Global { // You can do this with 'struct' & omit 'public'
public:
static int myglobalint;
};
And in global.cpp:
int Global::myglobalint = 0xbeef;
There's really no advantage doing it with an extern or class members - but unless it's some kind of global setting or flag, if you're resorting to storing state globally you probably need to put some thought into your design.
If you really do need global variables, for example, state or configuration that really has no other place to live, I would choose the class-static approach over a mess of extern's.
extern is a storage class in C. How exactly does it work? The output of the code given below is 20. How is this the output?
#include <stdio.h>
int main()
{
extern int a;
printf("%d", a);
return 0;
}
int a=20;
It means three things:
The variable has external linkage, and is accessible from anywhere in the program;
It has static storage duration, so its lifetime is that of the program (more or less); and
The declaration is just a declaration, not a definition. The variable must also be defined somewhere (either without the extern, or with an initialiser, or in your case, both).
Specifically, your extern int a; declares that the variable exists, but doesn't define it at that point. At this point, you can use it, and the linker will make sure your use refers to the definition. Then you have the required definition, int a=20; at the end, so all is well.
extern in this case indicates that the symbol a is defined in a different location, such as a different module. So the linker looks for a symbol with the same name in all of the modules that are linked, and if one exists then it sets the address to your local variable a with the address to the externally defined variable. Since you have another a defined outside of your main() function, the a inside your main() function is (basically) the same variable as the one outside.
Since the global a is initialized before the main function executes, the value is 20 by the time you access it.
extern means i declare a variable, just like you implement a function in a source file and declare the prototype in a header to allow other source file to use it.
If you put a global variable in a source file, and use a header to declare it with the extern keyword, each source file including the header will see the variable.
The linker will do the job to tie everything just as it does with functions
extern as a storage class specifier tells the compiler that the object being declared is not a new object, but has storage elsewhere, i.e., is defined elsewhere. You can try this experiment with your code to see how it works. Leave out the keyword extern in your declaration of int a in main(). Then your printf() will print some garbage value, as it would be a new definition of an int with the same identifier, which would hide the global a declared elsewhere.
You use extern to tell the compiler that the variable is defined elsewhere. Without extern in your program compiler would define another variable a (in addition to this in the global scope) in your main() function that would be printed uninitialized.
I would like a function that is not a member of a class and is accessible from any class.
I assume I would have to #include the header file where the function is declared, but I don't know where to define such a global function.
Are there good reasons against having such a function in the first place?
you need a body (in a cpp file):
int foo()
{
return 1;
}
and a definition/prototype in a header file, which will be included before any use of the function:
#ifndef MY_FOO_HEADER_
#define MY_FOO_HEADER_
int foo();
#endif
then using it somewhere else:
#include foo.h
void do_some_work()
{
int bar = foo();
}
or use an inline function (doesn't guarantee it'll be inlined, but useful for small functions, like foo):
#ifndef MY_FOO_HEADER_
#define MY_FOO_HEADER_
inline int foo()
{
return 1;
}
#endif
alternatively you can abuse the C-style header based functions (so this goes in a header, the static forces it to exist in a single compilation unit only, you should avoid this however):
#ifndef MY_FOO_HEADER_
#define MY_FOO_HEADER_
static int foo()
{
return 1;
}
#endif
What you are calling global function is usually called a free function and they are A Good Thing.
You would define it just like a class' member function, but outside of that class' scope.
double squared(double x) {
return x*x;
}
Simple functions you can define with the inline keyword in the header file, or just declare it there
double squared(double x);
and put the implementation (first example) into the *.cpp file.
In a header file:
// someheader.h
#ifndef MY_GLOBAL_FUN
#define MY_GLOBAL_FUN
void my_global_fun();
#endif
In an implementation file:
#include "someheader.h"
void my_global_fun()
{
// ...
}
In other files that require that function:
#include "someheader.h"
void f()
{
my_global_fun();
}
Free functions like this are useful and there are not many arguments against using them. Depending on your use case, its likely appropriate to put these functions in a specific namespace to avoid name collision with other libraries you may be using.
Think of main(). The function is kind of just...there. It's not within any class, struct or namespace. You just declare and give it a body. Of course, in the case of functions that are not main, it's best to put a prototype in a header and the define it in a .cpp file.
Remember, C did not have classes and structs could not hold member functions. There was nothing wrong with free functions then and there isn't now.
You have to declare its prototype in header file and define it in implementation file.
//file.h
void foo();
//file.cpp
void foo ()
{}
To shortly answer your second question, Global functions are needed when they are used by several different classes and types in a generic way. For example math functions.
Otherwise, in general you may avoid so many global functions. Also you should avoid having a static local member or global data associated with such function (so that you don't have to worry about thread safety).
In addition to the answer by #Necrolis, the use of static is deprecated in favour of unnamed namespaces. However, use of unnamed namespaces and static both creates separate copies for each translation unit which increases the size of binary. The use of inline is better than both of these in this sense.
These solutions allow for more usage specific optimisations by compilers but are less instruction cache friendly compared to definition in a source file and then linking.
If I have a class in outside.h like:
class Outside
{
public:
Outside(int count);
GetCount();
}
How can I use it in framework.cpp using the extern keyword, where I need to instantiate the class and call GetCount?
Edit:
#include is not allowed.
Everyone here is a bit too gentle.
There is ABSOLUTELY NO REASON why you would not want to include the .h file.
Go for it and include the file!
Just to clarify. It is impossible to extern the class:
class Outside
{
public:
Outside(int count);
GetCount();
}
But, once you have the class available in framework.cpp, you CAN extern an object of type Outside. You'll need a .cpp file declaring that variable:
#include "outside.h"
Outside outside(5);
And then you can refer to that object in another file via extern (as long as you link in the correct object file when you compile your project):
#include "outside.h"
extern Outside outside;
int current_count = outside.GetCount();
extern is used to say "I KNOW a variable of this type with this name will exist when this program runs, and I want to use it." It works with variables/objects, not classes, structs, unions, typedefs, etc. It's not much different from static objects.
You may be thinking about forward declaring classes to cut down on compile times, but there are restrictions on that (you only get to use the objects as opaque pointers and are not able to call methods on them).
You may also mean to hide the implementation of Outside from users. In order to do that, you're going to want to read up on the PIMPL pattern.
Update
One possibility would be to add a free function to Outside.h (I've also added a namespace):
namespace X {
class Outside {
int count_;
public:
Outside(int count) : count_(count) { }
int GetCount()
{
return count_;
}
};
int GetOutsideCount(Outside* o);
}
Implement that function in a .cpp file. While you're at it, you might as well make the global variable that you intend to extern (note, the variable itself does not need to be a pointer):
#include "outside.h"
namespace X {
int GetOutsideCount(Outside* o)
{
return o->GetCount();
}
}
X::Outside outside(5);
And then do this in your program (note that you cannot call any methods on outside because you did not include outside.h and you don't want to violate the one definition rule by adding a new definition of the class or those methods; but since the definitions are unavailable you'll need to pass pointers to outside around and not outside itself):
namespace X {
class Outside;
int GetOutsideCount(Outside* o);
}
extern X::Outside outside;
int main()
{
int current_count = GetOutsideCount(&outside);
}
I consider this an abomination, to put it mildly. Your program will find the GetOutsideCount function, call it by passing it an Outside*. Outside::GetCount is actually compiled to a normal function that takes a secret Outside object (inside Outside::GetCount that object is referred to via the this pointer), so GetOutsideCount will find that function, and tell it to dereference the Outside* that was passed to GetOutsideCount. I think that's called "going the long way 'round."
But it is what it is.
If you aren't married to using the extern keyword, you can instead go full "let's use C++ like it's C" mode by adding the following two functions in the same way (i.e., via forward declarations and implementing right next to int GetOUtsideCount():
Outside* CreateOutsidePointer(int count)
{
return new Outside(count);
}
void DestroyOutsidePointer(Outside* o)
{
return delete o;
}
I'm more willing to swallow that. It's a lot like the strategy used by the APR.
You don't make classes extern. Just include "outside.h" and create an instance of Outside.
you cant extern the class, but you can extern a function that creates an instance.. In the consumer code:
class Outside;
extern Outside* MakeAnOutside(int count);
extern int GetOutsideCount(Outside* outside);
Then in outside.h:
Outside* MakeAnOutside(int count)
{
return new Outside(count);
}
int GetOutsideCount(Outside* outside)
{
return outside->GetCount();
}
but.. this may not be a good idea..
Include files are for definitions, including class definitions. extern is for variables.
If you don't have the definition of a class in a source file, about the only thing you can do with it is declare it with class Outside; and pass instances around by pointer. You can't actually do anything with the instances, including construction, destruction, or calling member functions like GetCount(). For this, you don't need extern at all; only if you want to refer to a variable in another source file, and that won't let you do anything additional with it.
There is no valid reason not to use #include here. The only alternative is to copy-and-paste the header file into the source file, and that's considerably worse. Anybody who tells you not to use #include does not understand C++, and obviously anybody who thinks extern has any relevance here certainly doesn't.
If at all possible, you should get an experienced C++ developer to help you learn, establish good coding styles, and mentor you in how to develop C++. I suspect you're doing other things that will turn out to be Bad Ideas later on.
If you had a silly requirement that #include is not allowed then you'd have to copy and paste the class declaration into your .cpp file. Need I say that'd be a very bad idea?
What is the reason for this requirement? It pains me to advise you how to do this. If you are trying to avoid long #include paths in your source files, this is a build problem not a source code problem.
You should add directories to the include path with the gcc -I option, or whatever the equivalent is for your compiler.
If you are really, really sure about this, you'd want something like this:
framework.cpp
// FIXME: Should #include "outside.h" but not allowed.
class Outside
{
public:
Outside(int count);
GetCount();
// Omitted
// void SomeUnusedMethod();
};
<code for framework.cpp here>
void UseOutside()
{
Outside o(5);
std::cout << o.GetCount() << std::endl;
}
I would then strongly recommend you leave the declaration as is so it's just straight copy-and-pasted from the header file. But if you want to trim it you can omit any non-virtual methods you don't use. You'll need to keep all variables.
I can only think of one use case where you could 'extern' a class without either #including the header or duplicating the class definition as others have suggested.
If you need to keep pointer to the class but you never dereference it directly, only pass it around, then you can do the following in your file:
class Outside;
class MyClass
{
Outside* pOutside;
void SetOutsidePointer(Outside *p) {pOutside = p;}
Outside* GetOutsidePointer() { return pOutside;}
/* the rest of the stuff */
}
This will only work if you never call pOutside->GetCount() or new Outside in your file.
Put the include for your Outside class in the StdAfx.h or any other headerfile that framework.cpp is already including.
I think you misunderstand the storage classes and one of them is the external.
"Objects and variables declared as extern declare an object that is defined in another translation unit or in an enclosing scope as having external linkage."
So marking extern is for variables not classes defination/declaration
So if you can not include the .h, I recommend you to build the .h and .cpp to be static lib or dll and use in your code
Yikes... we put classes in header files and use #include in order to duplicate class (or other) declarations into multiple cpp files (called compilation units).
If you really can't use #include, you're left with a manual copy, as suggested above, which has the obvious problem of becoming outdated when someone changes the original. That'll completely break your test code with hard to track crashes.
If you insist on going down the path of this manual copy, you do need the entire class declaration. Technically, you could omit certain bits and pieces, but this is a bad idea -- clearly your team doesn't have deep understanding of C++ constructs, so you're likely to make a mistake. Second, the C++ object model is not standardized across compilers. Theoretically even a simple non-virtual method could change the model, breaking your test.
A "long path" is really not a great reason not to include a file directly. But if you really can't, copy the entire header file in where #include would have been -- that's exactly what the C preprocessor is going to do anyway.