Hi, I have been programming in C for some time and now I am trying my hand at C++.

As we all know, global variables are baaaaad...

However, I am developing a collection of classes and I need them all to share a common variable (a time step) whose value will be defined by the user. As far as my understanding of C++ goes, I could either use a global variable, or my classes could be derived from a "master class" in which this variable is defined as "protected". But I'm sure there must be another, more elegant solution...

Could you please let me have your input on this one?

Thanks in advance

Jose

Recommended Answers

All 14 Replies

I would have the variable passed into the constructor of each class

You can create a namespace for all of your classes and then add that global variable in that namespace.

You may consider changing your constructors to your classes to add an additional parameter. As the class is created that variable will be used as a parameter that you can share between all classes.

P.S. Nathan seemed to beat me to it.

You can create a struct whose sole purpose if to share const global variables, for example :

struct EnvironmentConstants{
 static const int TIME_STEP = 1; //in sec
 static const int SCREEN_WIDTH = 100; //in pixels
 //.. and so on
};

and call it like so :

void update(){
  foreach( Entity e : EntityList){
     update(*this,EnvironmentConstants::TIME_STEP);
  }
}

Quote: "However, I am developing a collection of classes and I need them all to share a common variable (a time step) whose value will be defined by the user."

Since the values is defined by user, its similar to a configuration value, therefore const is probably not what you want.

A singleton that the user can initialize at startup maybe another alternative

Guys, thank you all for your kind answers.

template<>, you are right, a constant is not what I need. However, could you please tell me what a singleton is?

Regards,

Jose

A singleton is a design pattern. It is a way to describe a class that get instantiated only once but can be shared by many callers. Here is an example:

class Timer {
   int x;
   Timer () : x(0) {} // Private
   static Timer * only_copy;
public:
   static Timer * instance () {
      if (! only_copy)
         only_copy = new Timer ();
      return only_copy;
   }
   int getX () { return x; }
};

ANd you would use it like

Timer * t = Timer::instance ();
int x = t->getX ();

Any code that calls Timer::instance () gets a handle to the same variable.

Note: The above is untested. It is meant to give you an idea of how to implement/use a singleton.

Thank you very much template<>, L7Sqr: a singleton is indeed a very elegant solution!

Cheers,

Jose

If you are going to use a singleton, do it correctly. The code that L7Sqr posted has two big flaws: before calling instance(), the pointer "only_copy" is not necessarily NULL, and thus, the test (!only_copy) is likely to be false even on the first use of instance(); second, there will be a different copy of "only_copy" in each translation unit (that might not be a concern to you right now, but better learn the proper way soon rather than later).

The recommended way of implementing a singleton is as follows:

//in Timer.h
class Timer {
   int x;
   Timer () : x(0) {} // Private
   Timer(const Timer&); //make the Timer class non-copyable (such that another instance cannot be created)
   Timer& operator=(const Timer&); //make non-assignable for the same reason.
public:
   static Timer& instance (); //return the instance by reference.
   int getX () { return x; }
};

//in Timer.cpp

Timer& Timer::instance() {
  static Timer only_copy; //static-scoped instance (initialized only once).
  return only_copy;       //return by reference.
};

Later, you can use it as:

Timer& t = Timer::instance();
  int x = t.getX();

Putting the "only_copy" instance as a static variable in the cpp file, you guarantee uniqueness across translation units (and modules), and you guarantee that it will be initialized at least once and exactly once.

commented: Thank you for the corrections. +1

I have implemented this singleton idea. However, my situation is as follows: I have a set of header files, with another set of corresponding .cpp files. I am defining my singleton within main() with a float value that all other classes require, and a corresponding public getValue() function.

What I don't see at this point is how can the member functions of my set of classes access the float value they need within my singleton. I guess I could use my singleton as a master class from which all other classes would be derived, or maybe I could use some friend functions. But I wonder if there is other, simpler way to do it.

Thanks in advance

Jose

>>I guess I could use my singleton as a master class from which all other classes would be derived
NO! Don't do that. Really, don't!

>>maybe I could use some friend functions.
Hissh, probably wouldn't do that either, sounds messy and unnecessary.

>>how can the member functions of my set of classes access the float value they need within my singleton.
If it makes sense for different part of the software to modify the float value at will, then provide a function to do that. In other words, have both a GetValue() and SetValue(float NewValue) functions defined in your singleton.

>>I am defining my singleton within main()
That's not the way to do it. You need a separate header for the singleton's declaration and a separate cpp file for the singleton's implementation (don't put any of the two in your main.cpp file, I mean, for real, it completely defeats the purpose of the singleton).

All the classes that need to access (public) members (data or functions) of the singleton should include the singleton's header and use the static member function to get the instance of the singleton on which to operate.

I don't see how this could cause any problems, as long as the public functions of your singleton are sufficient for the purpose that any classes could make of it. If your singleton doesn't provide enough access to its members, add access to them, that's all (but don't abuse, because generally it is preferable not to expose more than needed).

commented: As always, good post. +13

There are also class static variables that can serve this purpose. The result is similar to the namespace solution mentioned by Saith, but probably better. It is not an uncommon approach to this problem.

Mike,

Thanks a lot for your observations...

>>I am defining my singleton within main()
>That's not the way to do it. You need a separate header for the singleton's >declaration and a separate cpp file for the singleton's implementation (don't put >any of the two in your main.cpp file, I mean, for real, it completely defeats the >purpose of the singleton).

My bad. What I meant is "I am instantiating my singleton within main()." I have a separate header file and a separate cpp file for the singleton.

>All the classes that need to access (public) members (data or functions) of the >singleton should include the singleton's header and use the static member function >to get the instance of the singleton on which to operate.

That's just what I am trying to figure out. I just don't know how to "use the static member function to get the instance of the singleton on which to operate." Could you please give me an example?

Cheers,

Jose

I already did in a previous post (using the name Timer), just to clarify:

//in MySingleton.h:
#ifndef MYSINGLETON_H
#define MYSINGLETON_H

class MySingleton {
   int value;
   // Private constructor, to forbid the construction from outside this class.
   MySingleton () : value(0) {} 
   //Non-copyable (such that another instance cannot be created)
   MySingleton(const MySingleton&);
   //Non-assignable for the same reason.
   MySingleton& operator=(const MySingleton&);
public:
   //Static member function that returns the instance of the singleton by reference.
   static MySingleton& instance (); 

   //other public member functions:
   int getValue() const { return value; }
   void setValue(int NewValue) { value = NewValue; }
};

#endif

//in MySingleton.cpp

//define the static member function in the cpp (this is crucial):
MySingleton& MySingleton::instance() {
  //Create a static-scope instance (initialized only once).
  static MySingleton only_copy;
  return only_copy;                  //return by reference.
};

Here is another example I wrote. And similarly on wikipedia (only for the description, because the code is in Java and should not be used in C++ because it is not safe (C++ has different rules about global objects like singletons)).

Guys,

Thank you very much for your time and guidance. I solved my problem with a singleton. Here's what I did:

class Timestep {
private:
   // timestep for the simulation
   float step;
   // Private constructors
   Timestep(){};
   Timestep(const Timestep&);
   // Private assignment operator 
   Timestep& operator= (const Timestep&);
public:
   // instantiates a single instance of the Timestep class
   static Timestep& Instance();
   // get and set functions
   float getStep(){return step;}
   void setStep(float = 1e-6);
};

#endif
#include <iostream>
#include <stdlib.h>
#include "Timestep.h" 
using namespace std;

Timestep& Timestep::Instance()
{
   static Timestep only_copy;
   return only_copy;
}

void Timestep::setStep(float st)
{step = st;}

I declare a single instance of my Timestep object in my main() like this

Timestep::Instance().setStep(DT);

And in the cpp of the classes that need to use this timestep I use

float step = Timestep::Instance().getStep();

"There can be only one"

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.