Search code examples
c++inheritancestatic-members

Shared variable among classes c++


I have multiple classes that need to share a single instance of another class. Publicly it should be unknown that this class exists. Is it appropriate to do something like the following? (Was tested as written)

#include <iostream>

class hideme
{
    private:
        int a;

    public:
        void set(int b) { a = b; }
        void add(int b) { a += b; }
        int get() { return a; }

        hideme() : a(0) { }
};


class HiddenWrapper
{
    protected:
        static hideme A;

};

hideme HiddenWrapper::A;

class addOne : public HiddenWrapper
{
    public:
        void add() { A.add(1); }
        int get() { return A.get(); }
};

class addTwo : public HiddenWrapper
{
    public:
        void add() { A.add(2); }
        int get() { return A.get(); }
};


int main()
{
    addOne a;
    addTwo b;

    std::cout << "Initialized: " << a.get() << std::endl;

    a.add();
    std::cout << "Added one: " << a.get() << std::endl;

    b.add();
    std::cout << "Added two: " << b.get() << std::endl;

    return 0;
}

For what it's worth, hideme is part of a library I'm attempting to design a facade around, and the other classes have members from the library that interact with the static hideme.

Additionally, if the header file written for HiddenWrapper has no corresponding source file, is that the best place to define its static member? With an include guard.

Is there any other method to solve this problem? As far as I could imagine (not terribly far) I could only solve it otherwise with friendship, which I am wary of.


Solution

  • You can prevent access to a class by not making it accessible outside the translation unit that uses it.

    // public_header.h
    
    class A {
        void bar();
    };
    class B {
        void foo();
    }
    
    // private_implementation.cpp
    #include "public_header.h"
    
    namespace {
      class hidden { void baz() {} };
    
      hidden h;
    }
    
    void A::bar() {
        h.baz();
    }
    void B::foo() {
        h.baz();
    }
    

    This class will be usable only by A::bar and B::foo. The type hidden and the variable h still technically have external linkage, but no other translation unit can say their names.