Reputation: 23
I want to make a global instance of a declared class shared between multiple .cpp
files in C++.
If you want to go fast, you can jump just after Expectations.
I know that many people said that I shouldn't use global variables for too much reasons... Read my explanations to understand why I do want them.
Step 1:
I was doing a C++ program with a class defined in a header file.
(The class's functions were declared in a cpp file.)
To explain it, I'll use a over-simplified hypothetical code. (Not the actual one.)
Simplified hypothetical Class.h
's code:
class Class {
public:
Class(intx,int y); //Does a lot of things
int OP1(int x); //Dummy operation
int OP2(int x); //Dummy operation
private:
type ManyVars;
}
Simplified hypothetical main.cpp
's code
#include "Class.h"
Class Member(140,360); //Declares it with parameters
bool Func1(int x) { //Dummy function
int y = Member.OP2(x);
return x > Member.OP1(y);
}
bool Func2(int x) { //Dummy function
int y = Member.OP2(x) * x;
return x > Member.OP1(y) +1;
}
int main() {
int x;
std::cin >> x;
y = Func2(x);
z = Func1(y * x / 5);
return Func2(z) + x / y;
}
As far I was, everything was working fine, but the code was monstrously big in main.cpp
because I had over 16 functions including 2 big ones!
(I show only two functions in my example to be simple.)
Step 2:
To make the code easier to read, I've moved the small functions in two others files Funcs.cpp
and Funcs.h
, like a library.
Then I moved the big functions into a new .cpp
file for each one to after being included in another header file.
(Hidden in example because it's like Funcs.cpp
.)
So, now the hypothetical main.cpp
looks like this:
#include "Class.h"
#include "Funcs.h"
Class Member(140,360);
int main() {
int x;
std::cin >> x;
int y = Func2(x);
int z = Func1(y * x / 5);
return Func2(z) + x / y;
}
And the hypothetical Funcs.cpp
looks like this:
#include "Class.h"
#include "Funcs.h"
bool Func1(int x) {
int y = Member.OP2(x);
return x > Member.OP1(y);
}
bool Func2(int x) {
int y = Member.OP2(x) * x;
return x > Member.OP1(y) +1;
}
Now comes an issue: Member
is only defined in main.cpp
but I need it also in Funcs.cpp
(and the others function files too).
Step 3:
I tried to add another input value of type Class
for each function and put Member
in it when used. It worked but the functions look awful! I don't want an extra parameter for each function! So I reverted the code to Step 1 for the moment.
What I want is any way to share the same instance between them. It's basically a global variable.
I want to keep same functions. int y = Member.OP2(x)
mustn't change whereas the beginning of each file could be changed.
I would like to be able to declare multiple such Member
s (I won't, but it must be possible to do it).
Does anyone know a way to share instances that way?
Please tell me if something is unclear.
Upvotes: 0
Views: 761
Reputation: 56
An alternative way to using globals is to exploit the Singleton Pattern by storing unique instance of the Class in static storage (Construct On First Use Idiom).
There is a question that explains the difference between this and john's answer (c.f. the C++ FAQ that addresses what is initialisation order fiasco and how does this approach avoid it).
template<int x, int y>
class Class
{
public:
static Class & get_instance()
{
static Class instance; // <- called only once!
return instance;
}
Class(const Class &) = delete;
Class & operator=(const Class &) = delete;
bool OP1(int a)
{
return a > x;
}
bool OP2(int b)
{
return b > y;
}
private:
Class() = default;
~Class() = default;
};
Then, you can get reference to the instance by the get_instance()
method as
auto& Member = Class<140,360>::get_instance();
Upvotes: 0
Reputation: 87997
Member
is a global variable. Share it using the usual technique that you would use for any global variable, declare it in a header file and define it (once) in a source file.
In a header file (say Class.h)
extern Class Member;
In main.cpp
Class Member(140,360);
That's it.
Upvotes: 5