Suppose I have a c++ program which with several classes which are related like this:
class Application
{
public:
// some functions
private:
BusinessLogic businessLogic;
// some variables
};
class BusinessLogic
{
public:
// some functions
private:
BusinessLogicSubClass1 businessLogicSubClass1;
BusinessLogicSubClass2 businessLogicSubClass2;
// some other member variables
};
BusinessLogicSubClass1
{
public:
// some functions
private:
SubClassOfSubClass1 subClassOfSubClass1;
// some other member variables
};
// etc.... (you get the idea I hope)
The point is, I know at compile time that there is an Application class that contains the BusinessLogic class which contains many sub classes. I also know that I only need one instance of the Application class. Now the question is how to decide on where to store such a class in memory?
As far as I know there are three main possibilities:
- on the stack:
int main()
{
Application application;
// do something with application
return 0;
}
- on the heap:
int main()
{
std::unique_ptr application = std::make_unique<Application>();
// do something with application
return 0;
}
- as a static:
int main()
{
static Application application;
// do something with application
return 0;
}
I read some information on the different types of memory. Based on what I read, I think it is not the best decision to store the application class on the stack. Mainly because the stack has a limited size and there is a very limited advantage of having the stack's automatic memory management (i.e. cleaning up variables that go out of scope) in this case.
I find it harder to decide however how to make the trade of between static and heap memory. In the simplified example above I think I go with static, because everything is known at compile time and static memory is said to be more efficient, compared to heap memory. (Does this way of thinking make any sense, or am I overlooking something here?)
However, there are some examples in which the choice becomes less evident. Suppose the application needs to be initialized via an .ini file. If you store the instance of the Application class on the heap, it will be possible to pass the initialization values via the constructor:
int main
{
IniFileReader reader;
InitializationValues iniValues = reader.GetIniValues();
std::unique_ptr application = std::make_unique<Application2>(iniValues);
// do something with application
return 0;
}
As far as I know, constructor initialization is considered to be better in terms of design than using some Init function like this:
int main
{
static Application3 application;
IniFileReader reader;
InitializationValues iniValues = reader.GetIniValues();
application.Init(iniValues);
// do something with application
return 0;
}
So here the choice is between cleaner code or a more efficient program. I realize this is sort of trade off is very much dependent on what type of application you intend to build.
What I am looking for is, if there are perhaps some rules of thumb or a sort of flow chart to decide where to store your classes?
Some (not necessarily good) examples of such rules could be:
- if you know everything about a class at compile time and you know there is only one instance, try to always store it as a static.
- always use the heap for objects that are shared between different threads.
- it does not really matter in this or that case, so chose for cleaner code.
And secondly, are there any general guidelines or design principles on where to put the static classes? I find it hard to decide where to put a static class if they need to be accessed by more than one other class. Globals are generally considered bad design for instance.
A practical example of such a dilemma, can be found in the following article on the state design pattern: https://gameprogrammingpatterns.com/state.html --> see subsection static states
I am not sure if the authors choice to put a static instance of each state in the base class is the best design. He also admits to put them there "for no particular reason". Any suggestions for a better place? Make a sort of state-database class? Make a singleton of each state?
edit: changed mistake in code pointed out by Neil Butterworth