Leorozol
Leorozol

Reputation: 23

How to share a variable across multiple source files in C++?

Summary of my goal

I want to make a global instance of a declared class shared between multiple .cpp files in C++.

Explanations

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.

Expectations

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 Members (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

Answers (2)

Vojtěch Hauser
Vojtěch Hauser

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

john
john

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

Related Questions