Going to all the effort of making a singleton object using the usual pattern isn't addressing the second part of your question - the ability to make more if needed. The singleton "pattern" is very restrictive and isn't anything more than a global variable by another name.
// myclass.h
class MyClass {
public:
MyClass();
void foo();
// ...
};
extern MyClass g_MyClassInstance;
// myclass.cpp
MyClass g_MyClassInstance;
MyClass::MyClass()
{
// ...
}
Now, in any other module just include myclass.h and use g_MyClassInstance as usual. If you need to make more, there is a constructor ready for you to call.
Going to all the effort of making a singleton object using the usual pattern isn't addressing the second part of your question - the ability to make more if needed. The singleton "pattern" is very restrictive and isn't anything more than a global variable by another name.
// myclass.h
class MyClass {
public:
MyClass();
void foo();
// ...
};
extern MyClass g_MyClassInstance;
// myclass.cpp
MyClass g_MyClassInstance;
MyClass::MyClass()
{
// ...
}
Now, in any other module just include myclass.h and use g_MyClassInstance as usual. If you need to make more, there is a constructor ready for you to call.
First off the fact that you want global variables is a 'code smell' (as Per Martin Fowler).
But to achieve the affect you want you can use a variation of the Singleton.
Use static function variables. This means that variable is not created until used (this gives you lazy evaluation) and all the variables will be destroyed in the reverse order of creation (so this guarantees the destructor will be used).
class MyVar
{
public:
static MyVar& getGlobal1()
{
static MyVar global1;
return global1;
}
static MyVar& getGlobal2()
{
static MyVar global2;
return global2;
}
// .. etc
}
It is just a static object. It is treated like any other global variable.
It will not be tied to any stack frames and will be created when the anything in the file is loaded for the first time.
Generally, people will not recommend relying on globals from a design perspective. It depends though, they can be reasonable.
If you are doing any sort of threading they can be an issue. You also want to minimize different parts of your application knowing that things are global variables, it leads to a lot of spaghetti code.
If the variable is not referenced outside of the file, or for cross-cutting concerns, then sometimes it can be a good thing.
The best advice is to avoid it when you can, don't over design it when you can't.
Objects that are global variables (or more precisely variables "at namespace scope") have static storage duration. This means they live until the end of the program, and they are initialized during program startup (either during the static or the dynamic initialization phase).
The order of initialization is not generally specified except that all such global objects are initialized before main() is called, and that the initialization does not introduce data races.
(Common techniques to sequence mutually dependent global initialization is to replace naked global variables with a global getter function and a block-static variable:
Foo & getFoo() { static Foo impl; return impl; }
Now any other global using getFoo() in its own constructor will be initialized after impl.)
Global Class Objects? - C++ Forum
How to create a global object/instance o - C++ Forum
C++: Declare a global class and access it from other classes? - Stack Overflow
Global Class - C++ Forum
You probably really do not want to do this, but if you must - in the file that contains main:
#include "A.h"
A a;
int main() {
...
}
and then in the files that need to access the global:
#include "A.h"
extern A a;
You will need to put the declaration of A in the A.h header file in order for this to work.
In C++ declaring a global instance of a class is a no-no.
You should instead use the singleton pattern, which gives you a single instance of your object accessible from the entire application.
You can find a lot of literature on C++ singleton implementation, but wikipedia is a good place to start.
Thread safe singleton pattern implementation has already been discussed on stackoverflow.
Using an extern variable is one option.
Another option is to have a function that returns a reference.
logging.h:
LogCenter& getGlobalLogCenter();
logging.cpp:
LogCenter& getGlobalLogCenter()
{
static LogCenter lc;
return lc;
}
//logcenter.h
#ifndef LOGCENTER_H_
#define LOGCENTER_H_
class LogCenter {
private:
int dummy;
public:
int getVal(){ return dummy; };
LogCenter() : dummy(0){};
LogCenter(int val) : dummy(val) {};
};
#endif // LOGCENTER_H_
xxx
// logcenter.cpp
#include "LogCenter.h"
LogCenter globalCenter;
xxx
//logger.h
#ifndef LOGGER_H_
#define LOGGER_H_
#include <string>
#include "LogCenter.h"
class Logger {
private:
LogCenter& center;
public:
Logger(); //automatically assigns the ominous global LogCenter object (reference) to center.
Logger(LogCenter&); //however, any other LogCenter object would work equally fine.
std::string print() { return std::string("This class uses logger ") + std::to_string(center.getVal()); };
};
#endif // LOGCENTER_H
xxx
// logger.cpp
#include "Logger.h"
extern LogCenter globalCenter;
Logger::Logger() : center(globalCenter) {};
Logger::Logger(LogCenter &logcenter) : center(logcenter) {};
xxx
// main.cpp
#include "Logger.h"
int main(int argc, char* argv[])
{
LogCenter logcenter2(2), logcenter3(3);
Logger logger1, logger2(logcenter2), logger3(logcenter3);
std::cout << logger1.print() << std::endl;
std::cout << logger2.print() << std::endl;
std::cout << logger3.print() << std::endl;
return 0;
}
output is:
This class uses logger 0
This class uses logger 2
This class uses logger 3
Yes, you can declare a global variable of any type, class or not.
No, you can't then "call" the constructor again inside a function to initialize it. You can however use the copy assignment operator to do it:
Foo foo;
int main()
{
foo = Foo(1, 3);
}
Or you can have a "setter" function that is used to set or reinitialize the object.
By the way, and depending on the data in the class, you might want to read about the rule of three.
It's certainly possible to have global objects. The correct way in your case is:
Foo foo(1, 3);
int main()
{
// ...
}
The global constructors run right after the initializations performed by
the C runtime startup code, and right before main() gets called.
In a nutshell, the C runtime initialization code:
- does some low-level initializations (e.g., setup the memory)
- calls the global constructors
- calls
main(), which in turn- calls
init()to do the Arduino-specific initializations - calls
setup() - repeatedly calls
loop()
- calls
The fine details are probably platform-specific. For AVR-based boards, they are documented in the avr-libc manual.
It is executed before the main() is called (in the main() there is setup() called and then loop() is called in infinite loop).
It has its own sections for the constructors and destructors: http://beefchunk.com/documentation/sys-programming/binary_formats/elf/elf_from_the_programmers_perspective/node4.html
Your doubt is correct, don't use global variables.
(Note: For this post, I mean variable in its true meaning, i.e. objects that may change.)
I can't say for sure which technique is the correct one without seeing your code, but normally you want to pass the variable as a parameter to whichever entity needs it:
void foo(Input input)
{
input.doSomething();
}
int main()
{
Input input;
input.doSomething();
foo(input);
}
Or, restrict it to a class as a member variable.
Update: Class examples
You can do it one or both of these ways:
class Person {
std::string name_;
public:
explicit Person(std::string const& name) : name_(name) {}
void set_name(std::string const& name) { name_ = name; }
}
void foo()
{
Person p("Bob Loblaw");
p.set_name("Slartibartfast");
}
There are two key downsides to using global variables:
1. They can be changed everywhere.
You generally want to enlist the compiler's aid in finding bugs and errors for you. If you allow yourself to modify a variable from all over your code, it is very hard for your compiler and yourself to track down an error. Consider the following scenario:
Input input; // global
void foo()
{
Input inputt;
input = someThingWeird;
}
This code will compile. If you're really unlucky, it will even work for a while. If you don't have a global, the code won't compile and the bug will be easy to find.
2. They increase coupling (and reduce testability).
By reading from a global variable, your entity (i.e. function, class, whatever) depends on that global variable. If some day you want to use something else, you'll have to do a lot of refactoring. What's more important, if you change an aspect of the global variable, you will need to update all parts of the code that uses it. This is a great opportunity for suble bugs to infiltrate your code and make your life miserable. A typical example is that you modify one part of your code, and a completely different part will break.
Using globals also makes your code hard to unit test, because it depends on the global variable.
@Lstor is absolutely correct. However, I'll like to add some things:
If you're using constants (indicated by the
constkeyword), they're okay as globals. This is because they cannot be changed elsewhere in the code, unlike global variables).I'd recommend
classes, especially when writing a game. When used properly, they will allow you to hide your data from entities that should not have access to them. However, it's best not to use them just to avoid globals, especially when they can still be passed around. They should serve some kind of role, even if your program doesn't revolve aroundclasses. In your case, you'll most likely have a Gameclassand possibly additionalclasses. More general info about this here.
One solution would be to use a Singleton for your global class. You can see for example this answer.
The problem here is that you are defining on class per compilation units (ie per .cpp file you compile) which means that would have effectively a different instance of your class in each of your cpp files.
You should also think about using the Singleton Design Pattern as it is rarely a good design to adopt when building an application. You can see this to understand more about its use cases!
As Thomas Caissard told, the solution is Singleton Pattern.
Here is how for anyone who is looking for solution rather than me...
Singleton.h
#ifndef Singleton_H
#define Singleton_H
class Singleton
{
private:
Singleton();
~Singleton();
static bool isInit;
public:
static Singleton* getInstance();
int foo;
};
#endif
Singleton.cpp
#include "Singleton.h"
bool Singleton::isInit=false;
Singleton* Singleton::getInstance()
{
static Singleton s;
return isInit? &s:0;
}
Singleton::Singleton()
{
isInit=true;
}
Singleton::~Singleton()
{
isInit=false;
}
main.cpp( or otherClass with same syntax )
#include "Singleton.h"
void main() {
Singleton* p = Singleton::getInstance();
p->foo = 123; // Use variable from everywhere with same value....
// Other staffs
}