Solved

Static class, Singleton, or global?

Posted on 2013-11-27
10
309 Views
Last Modified: 2013-12-02
(I come from a C# background, which doesn't translate easily to C++ I've learned.)

State Design Pattern

I have a ClassOne, and in this class it holds another class which is the current state, say classes StandardStateA, StandardStateB.

I also have a ClassTwo, and a ClassThree, which also have a current state class.

There's no reason to have multiple copies of StandardStateA, StandardStateB. The big deal is to be able to easily switch between them.

But static classes don't exist in C++ I'm told. So what other options do I have?

Do I create a global variable instance of StandardStateA, StandardStateB, creating it outside of any class? Or do I go with Singleton? Perhaps I say "forget it" and just go with each class creates its own personal identical copy of StandardStateA and StandardStateB? Is this one of those situations where there is no right answer?
0
Comment
Question by:deleyd
10 Comments
 
LVL 24

Expert Comment

by:chaau
ID: 39682774
I am not sure why you refer to your  StandardStateA, StandardStateB as classes. They seem to me more like enum values. I would design the whole thing as:
enum StandardState
{
   StandardStateA,
   StandardStateB
};
class ClassOne
{
public:
   StandardState state;
};
class ClassTwo
{
public:
   StandardState state;
};
class ClassThree
{
public:
   StandardState state;
};

Open in new window

Explanation: enum has only the limited number of values, but I believe you know this anyway. If you are concerned that your StandardState becomes public then you can place it inside a class, like this:
class ClassOne
{
public:
enum StandardState
{
   StandardStateA,
   StandardStateB
};
   StandardState state;
};
class ClassTwo
{
public:
   ClassOne::StandardState state;
};
class ClassThree
{
public:
   ClassOne::StandardState state;
};

Open in new window

BTW, you could have a class consisting of only static members. The class will become static as well, like this:
class ClassA
{
   static void foo();
   static void bar();
}

Open in new window

When you call methods from this class, you do not need to instantiate the actual class object, like this:
void main()
{
   ClassA::foo(); // calling a static member of ClassA
}

Open in new window

0
 

Author Comment

by:deleyd
ID: 39682844
Well the idea of the State Design Pattern is to have a slot where you can plug in a class.
State currentState;
...
currentState = new StateA;
...
currentState.MethodA;
currentState.MethodB;
...

//later..
currentState = new StateB;

//and we can then go back and call MethodA and MethodB, and we'll get the StateB versions of MethodA and MethodB.

Open in new window

However in this method we always instantiate a new instance of whatever class we want to be the current class. I'm trying to avoid all that creating and destroying.

Aren't enum values just a fancy way to hide integers? Or have they evolved to include classes?
0
 
LVL 29

Expert Comment

by:pepr
ID: 39682885
If static class is the one that cannot be instantiated, then you can do the same also in C++. It is only not named that way. Static classes are actually only collection of functions and variables in a separate namespace. You can do the same with plain functions and variables in a C++ namespace. In other words, the need for static classes in C# are the proof that you need sometimes something more than pure OO approach.

Anyway, you can have a static instance of a class in C++, i.e. the one that was not created via new. You can declare it at a global level in a selected .cpp file, and make it available elsewhere via extern in some .h file.

However, there is probably easier, better, and easily understandable imlementation of a singleton pattern in C++. It is called Meyer's singleton -- here is the detailed original aticle by the authors http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf. When using C++11, it is thread safe. It need not to be in older C++. The page http://www.devarticles.com/c/a/Cplusplus/C-plus-plus-In-Theory-The-Singleton-Pattern-Part-I/4/ shows the example implementation for the Log class:
class Log {
public:
  static Log& Instance() {
    static Log theLog;
    return theLog;
}
  void Write(char const *logline);
  bool SaveTo(char const *filename);
private:
  Log();          // ctor is hidden
  Log(Log const&);      // copy ctor is hidden
  Log& operator=(Log const&);  // assign op is hidden

  static std::list<std::string> m_data;
};

Open in new window

0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 12

Expert Comment

by:trinitrotoluene
ID: 39683269
I would suggest that you look at the problem not from a programming perspective. What is the problem you are trying to solve?

What are ClassOne, ClassTwo and ClassThree going to be represent and how many objects of them do you need at runtime? How do they interact with each other.?

Will all objects of a particular class exist in the same state? Can objects of different classes exist in the same state?

Let us assume there are only 3 state objects : On, Off and Floating
Also assume there are 5 objects : Class1Obj1, Class2Obj1, Class3Obj1, Class3Obj2, Class2Obj2.

If you create a singleton to represent each of these states then just one object of each of these states is going to exist.

How would you share these 3 state objects amongst the 5 object?


Perhaps you want to create just one state object which changes its internal state value at runtime and which can be accessed and influenced by all the 5 objects.
0
 

Author Comment

by:deleyd
ID: 39683956
Currently I have "class within a class within a class, within a class."

I have a Controller,

the Controller has a currentMenu

the currentMenu has a currentMenuItem

the currentMenuItem has a currentEventHandler.

There are (currently) two possible currentEventHanders:  one is the regular one that does the same thing for all the menu items on all the menus. I'll call that my StandardEventHandler. Then there's an 'Edit' mode the currentMenuItem can be in, which requires a different set of Event Handlers, I'll call that my EditEventHandler.

There are a dozen menus and each menu has a dozen menu items. But I don't need a dozen squared * 2 event handler class instances, I only need 2.

(The actual names are slightly different, since Visual Studio complains if I try to make a class named 'Menu')

Helpful would be a simple working example of a MenuItemClass
which has a currentEventHandler
and two possible choices for that currentEventHandler
which are StandardEventHandler and EditEventHandler
(both which implement IEventHandler);
designed so I can have a hundred Menu Items,
but not a hundred different Event Handler subclass instances.
0
 
LVL 29

Expert Comment

by:pepr
ID: 39684074
What framework do you use? And also, is it to be a native C++ application or the .NET?
0
 

Author Comment

by:deleyd
ID: 39684152
Native C++. Visual Studio 2010.
0
 

Author Comment

by:deleyd
ID: 39684764
It occurred to me maybe I needn't be so concerned about instantiating 100 copies of the same class. If all the methods are static I would hope C++ would be smart enough not to make 100 copies, but just have everyone use the same class. Though I'm not sure if that will work in a multithreaded environment.
0
 
LVL 29

Expert Comment

by:pepr
ID: 39684811
I suggest to answer (for yourself, and for us) the trinitrotoluene's questions. It really helps to understand what you are solving and whether it should be solved this or that way.

Aren't enum values just a fancy way to hide integers? Or have they evolved to include classes?

Enums came from other languages. Their original intention was to name the otherwise magic numbers, and to add a specific type to the named values. The C-family started with simple "enum value is equal to certain integer". However, the enum type itself could be checked.

C++11 adds stronger type checking where the enum value is not implicitly converted to integer; hence, it cannot be used interchangably with the same integer value. It is defined a enum class name {...}; or enum struct name {...};.

By the way, if you can, switch to Visual Studio 2013. The C++11 is really nice.
0
 
LVL 29

Accepted Solution

by:
pepr earned 500 total points
ID: 39685363
If all the methods are static I would hope C++ would be smart enough not to make 100 copies

Methods need not to be static. Even the normal method do not increase the size of the instances. The method code is shared by instances. Mostly only the data members define the instance size.
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

830 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question