Transforming SysInfo into a singleton

Promises are made to be kept: we will now transform the SysInfo class into a singleton. C++ offers many ways to implement the singleton design pattern. We will explain one of them here. Open the SysInfo.h file and make the following changes:

class SysInfo 
{ 
public: 
    static SysInfo& instance(); 
    virtual ~SysInfo(); 
 
    virtual void init() = 0; 
    virtual double cpuLoadAverage() = 0; 
    virtual double memoryUsed() = 0; 
 
protected: 
    explicit SysInfo(); 
 
private: 
    SysInfo(const SysInfo& rhs); 
    SysInfo& operator=(const SysInfo& rhs); 
}; 

The singleton must guarantee that there will be only one instance of the class and that this instance will be easily accessible from a single access point.

So the first thing to do is to change the visibility of the constructor to protected. This way, only this class and the child classes will be allowed to call the constructor.

Since only one instance of the object must exist, allowing the copy constructor and the assignment operator is nonsense. One way to solve the problem is to make them private.

C++ tip Since C++11, you can define a function as deleted with the syntax void myFunction() = delete. Any use of a deleted function will display a compile-time error. It's another way to prevent the use of the copy constructor and the assignment operator with a singleton.

The last change is the "unique access point" with a static function instance that will return a reference of the SysInfo class.

It is now time to commit singleton changes to the SysInfo.cpp file:

#include <QtGlobal> 
 
#ifdef Q_OS_WIN 
    #include "SysInfoWindowsImpl.h" 
#elif defined(Q_OS_MAC) 
    #include "SysInfoMacImpl.h" 
#elif defined(Q_OS_LINUX) 
    #include "SysInfoLinuxImpl.h" 
#endif 
 
SysInfo& SysInfo::instance() 
{ 
    #ifdef Q_OS_WIN 
        static SysInfoWindowsImpl singleton; 
    #elif defined(Q_OS_MAC) 
        static SysInfoMacImpl singleton; 
    #elif defined(Q_OS_LINUX) 
        static SysInfoLinuxImpl singleton; 
    #endif 
 
    return singleton; 
} 
 
SysInfo::SysInfo() 
{ 
} 
 
SysInfo::~SysInfo() 
{ 
} 

Here you can see another Qt cross-OS trick. Qt provides some macro Q_OS_WINQ_OS_LINUX, or Q_OS_MAC. A Qt OS macro will be defined only on the corresponding OS. By combining these macros with a conditional preprocessor directive#ifdef, we can always include and instantiate the correct SysInfo implementation on all OSes.

Declaring the singleton variable as a static variable in the instance() function is a way to make a singleton in C++. We tend to prefer this version because you do not need to worry about the singleton memory management. The compiler will handle the instantiation the first time as well as the destruction. Moreover, since C++11 this method is thread safe.