Static member functions in C++ - c++

I was going through one of the examples of C++, for cloning of an object.
#ifndef CLIPBOARDSTACK_H
#define CLIPBOARDSTACK_H
#include <QStack>
#include "getEntity.h"
class clipboardStack
{
public:
static clipboardStack *instance()
{
if (!inst)
inst = new clipboardStack;
return inst;
}
void push(getEntity *entity)
{
clips.push(entity);
}
getEntity *pasteEntity()
{
if (clips.count() == 0)
return 0;
return clips.last();
}
getEntity *pop()
{
if (clips.count() == 0)
return 0;
return clips.pop();
}
bool isEmpty() const
{
return clips.empty();
}
private:
QStack<getEntity *> clips;
static clipboardStack *inst;
};
#endif // CLIPBOARDSTACK_H
where getEntity is:
#ifndef GETENTITY_H
#define GETENTITY_H
#include <QGraphicsItem>
class getEntity : public QObject, public QGraphicsItem
{
public:
getEntity(QObject *parent = 0) : QObject(parent) {}
virtual ~getEntity() {}
virtual getEntity *clone()
{
return 0;
}
};
#endif // GENTITY_H
But I couldn't get what exactly the line means.
What is the meaning of the line:
static clipboardStack *instance()
{
if (!inst)
inst = new clipboardStack;
return inst;
}
Can someone explain me what does above line exactly do, and the two classes in brief?

static clipboardStack *instance()
{
if (!inst)
inst = new clipboardStack;
return inst;
}
This is a code for singleton pattern. If there is no instance of class clipboardStack, then it would create it else it would return already created instance.
NOTE:- This implementation of singleton is not thread-safe.

static clipboardStack *instance()
{
if (!inst)
inst = new clipboardStack;
return inst;
}
This is singleton pattern, usually they write this pattern for having only one instance of the class at any point of time.
If there is no instance for the clipboardstack created. you just create one. next time when someone calls instance(), it delivers the same instance created before. No new instance gets created again.
I guess you have to initialize the clipboardstack pointer to NULL. Its a good programming practice. If you are in a debug mode this might point to uninitialized memory like 0xCDCDCD for instance, which is not null and everytime you call instance(), you will get 0xCDCDCD and you will end up crashing the program.

Related

Crash when method of class is executing but smart pointer deleted the object

I faced a problem with C++ memory management and smart pointers.
I have a code to demonstrate you the problem:
#include <memory>
class Closeable
{
public:
virtual void Close() = 0;
};
class DisconnectionHandler
{
public:
virtual void HandleDisconnection() = 0;
};
class EventHandler
{
public:
virtual void HandleEvent() = 0;
};
class Notifier
{
public:
virtual void OnDisconnection() = 0;
};
class RemoteSystem : public Closeable
{
public:
void SetReceiveDataEventHandler(const std::shared_ptr<EventHandler>& receive_data_event_handler) {
this->receive_data_event_handler_ = receive_data_event_handler;
}
void Close() override { this->receive_data_event_handler_ = nullptr; }
// In this example to simplify the code I just call this method from the main function.
void OnDataReceived() { this->receive_data_event_handler_->HandleEvent(); }
private:
std::shared_ptr<EventHandler> receive_data_event_handler_;
};
class ReceiveDataEventHandler : public EventHandler
{
public:
explicit ReceiveDataEventHandler(const std::shared_ptr<DisconnectionHandler>& disconnection_handler)
: disconnection_handler_(disconnection_handler) {}
void HandleEvent() override {
// Some code of receiving data.
// But we can find out that connection was closed and we must call the disconnection handler.
if (this->IsConnectionClosed()) {
this->disconnection_handler_->HandleDisconnection();
return;
}
// Some other stuff..
}
private:
[[nodiscard]] bool IsConnectionClosed() const {
// In the example code I just return true.
return true;
}
private:
const std::shared_ptr<DisconnectionHandler> disconnection_handler_;
};
class RemoteSystemDisconnectionHandler : public DisconnectionHandler
{
public:
explicit RemoteSystemDisconnectionHandler(const std::shared_ptr<Closeable>& closeable_remote_system,
Notifier* notifier)
: closeable_remote_system_(closeable_remote_system), notifier_(notifier) {}
~RemoteSystemDisconnectionHandler() { printf("Destructed.\n"); }
void HandleDisconnection() override {
this->closeable_remote_system_->Close();
printf("Closed.\n");
this->notifier_->OnDisconnection();
printf("Notified.\n");
}
private:
const std::shared_ptr<Closeable> closeable_remote_system_;
Notifier* const notifier_;
};
class ClientNotifier : public Notifier
{
public:
void OnDisconnection() override { printf("Disconnected.\n"); }
};
int main() {
ClientNotifier notifier;
auto remote_system = std::make_shared<RemoteSystem>();
{
// Scope for losing references in the main function after SetReceiveDataEventHandler.
auto disconnection_handler = std::make_shared<RemoteSystemDisconnectionHandler>(remote_system, &notifier);
auto receive_data_event_handler = std::make_shared<ReceiveDataEventHandler>(disconnection_handler);
remote_system->SetReceiveDataEventHandler(receive_data_event_handler);
}
// Only in the example.
remote_system->OnDataReceived();
return 0;
}
You can also run this code. In this example program crashes on the line this->notifier_->OnDisconnection(). The output of the program:
Destructed.
Closed.
*crash*
This occurs because of losing the last reference to the ReceiveDataEventHandler when calling method RemoteSystem::Close from RemoteSystemDisconnectionHandler::HandleDisconnection, accordingly, losing the reference to the RemoteSystemDisconnectionHandler and deleting this object. After the Close method and deleting both objects of classes RemoteSystemDisconnectionHandler and ReceiveDataEventHandler it returns to the RemoteSystemDisconnectionHandler::HandleDisconnection method and prints 'Closed.' to the output, but since the object has been already deleted, the next line occurs an error, because now this is deleted and any access to it occurs memory exception.
I also tried to rewrite this code on Java and it works fine, unlike C++.
So, I want to ask you guys if there is a solution for this problem in the C++ community?
I thought C++ had no problems with memory management since smart pointers exist, but appearently I was wrong.
Hope for your help!
Thanks in advance!
A simple solution is to make a copy of the shared_ptr before invoking the method on it:
void OnDataReceived()
{
auto temp = this->receive_data_event_handler_;
if (temp)
{
temp->HandleEvent();
}
}
temp will keep the pointer alive until after the method invocation has completed.
However note that if you are using multiple threads in your real code, std::shared_ptr is not thread safe so you need to introduce a mutex to protect access to receive_data_event_handler_:
class RemoteSystem : public Closeable
{
public:
void SetReceiveDataEventHandler(const std::shared_ptr<EventHandler>& receive_data_event_handler) {
this->receive_data_event_handler_ = receive_data_event_handler;
}
void Close() override
{
std::unique_lock lock(mutex);
this->receive_data_event_handler_ = nullptr;
}
// In this example to simplify the code I just call this method from the main function.
void OnDataReceived()
{
std::shared_ptr<EventHandler> temp;
{
std::unique_lock lock(mutex);
temp = this->receive_data_event_handler_;
}
if (temp)
{
temp->HandleEvent();
}
}
private:
std::shared_ptr<EventHandler> receive_data_event_handler_;
std::mutex mutex;
};

Singleton Class not working into multiple files

Say I have this code:
#include <iostream>
using namespace std;
class Something
{
int field1;
static Something *nill;
static bool initialized;
static void initialize() {
if (initialized)
return;
initialized = true;
}
public:
static Something* Nill()
{
initialize();
return nill;
}
static Something* Singleton(int field1)
{
initialize();
Something *ret = new Something();
ret->field1 = field1;
return ret;
}
}
Something* Something::nill = new Something();
bool Something::initialized = false;
int main(void)
{
Something *smth = something->Nill();
return 0;
}
Why isn't 'Something' a Singleton Class, and how could I make it one? Also how could I split this code into 2 files a .h and a .cpp? I had problems with that because I have some global variables here and I don't know how to use them in other files..
This is not a singleton class. Singleton class implies that in any given time you cannot have more than 1 instance of the class. In your example, you're not only creating a new instance but even return new class objects in its methods.
Make a default constructor protected (copy or move constructors too if you really want to be sure it's as singleton). Then use your static 'nill' as shown below:
class Something {
protected:
Something() = default;
...
int main() {
Something::nill->Nill();
...
P.s. Are you sure you need a singleton? Your methods say opposite.

How to declare a global QWidget?

I want to have a class, which extends QWidget, that I can access in my whole program. I've already tried to declare it in the main.cpp (but this is obsiously not declared in the other files) or to to it after the class declaration (in this case, if I include the file more than once, I get the error multiple declaration).
Is it possible to the Widget as global, and if yes, how ?
Edit :
What I want to do is to write informations on an second window, which is an instance of the class Console (I have written that class).
Then, I have the class MainWindow, with the classes it contains; calculation_widget, and variable_widget, which contain respectively a list of calculations and variables.
I want to be able to write on the Console window from all those classes.
I don't recommend using this, but it would be better than a global pointer. In case you need your window(-s) only once in your application you could use the Singleton (Anti-)pattern.
This is the SingletonTemplate class.
#ifndef __CSingletonTemplate_H__
#define __CSingletonTemplate_H__
template <class T> class CSingletonTemplate
{
public:
static T* GetInstance()
{
if (m_Instance == 0)
{
m_Instance = new T();
}
return m_Instance;
}
static T& GetRefInstance()
{
if (m_Instance == 0)
{
m_Instance = new T();
}
return *m_Instance;
}
static void Release()
{
if (m_Instance != 0)
{
delete m_Instance;
m_Instance = 0;
}
}
protected:
CSingletonTemplate() { ; }; // Hidden constructor
CSingletonTemplate(CSingletonTemplate const&) { ; }; // Hidden copy constructor
CSingletonTemplate& operator=(CSingletonTemplate const&) { ; }; // Hidden assign operation
~CSingletonTemplate() { ; }; // Hidden destructor
private:
static T* m_Instance;
};
template <class T> T* CSingletonTemplate<T>::m_Instance = 0;
#endif // __CSingletonTemplate_H__
You use it by declaring a class like follows:
class MyWindow : public CSingletonTemplate<MyWindow>
{
friend class CSingletonTemplate<MyWindow>;
private:
MyWindow();
virtual ~MyWindow();
Q_DISABLE_COPY(MyWindow);
};
And you can use this class my calling MyWindow::GetInstance()->...
For more information about the Singleton Pattern visit: https://sourcemaking.com/design_patterns/singleton

C++ singleton in constructor

Is this possible?
class A {
static A *instance = NULL;
public:
A () {
if (instance) {
this = instance;
} else {
instance = this;
}
}
}
Does it have leak memory?
Do I need to oveload new operator?
No. Overlooking your compiler errors, your class won't work.
#Galik has provided invaluable sources for how you'd actually want to construct a singleton. But let's look at yours.
class A {
static A *instance = NULL; // NULL isn't even a thing, but assuming you mean nullptr you can't assign a static like this
public:
A () {
if (instance) {
this = instance; // this can't be assigned
} else {
instance = this; // this is correct
}
}
};
Which would give you the following:
class A {
static A *instance;
public:
A () {
// if there's no instance, this is the one we'll use
if (!instance) {
instance = this;
}
}
};
A* A::instance = nullptr;
Which doesn't stop you from constructing more than one anyway.
Not possible. If the constructor is exposed and called, a new object of A is inevitably created. The most elegant and widely used implementations of C++ singleton classes use static methods to return the single static instance, while hiding (e.g. make private accessible) the constructor.
Here's an example:
class A {
private:
static A *instance_; // use nullptr since C++11
A() {}
public:
static A& instance() {
if (!instance_)
instance_ = new A();
return *instance_;
}
};
A* A::instance_ = nullptr;
You cannot assign a value for this

Fails to allocate derivative class to base class pointer?

I have a AbstractFactory, WinFactory and IOSFactory classes.
AbstactFactory inheritences WinFactory and IOSFactory as the following:
class IOSFacetory {
private:
IOSRectButton *_rectbtn;
IOSCircularButton *_circbtn;
public:
IOSFacetory() : _rectbtn(NULL), _circbtn(NULL) {} // set rectbtn to null
IOSRectButton* getIOSRectBtn () {
if(!_rectbtn) _rectbtn = new IOSRectButton;
return _rectbtn;
}
IOSCircularButton* getIOSCircBtn() {
if(!_circbtn) _circbtn = new IOSCircularButton;
return _circbtn;
}
~IOSFacetory() {
if(_rectbtn) delete _rectbtn;
if(_circbtn) delete _circbtn;
}
};
class WinFacetory {
private:
WinRectButton *_rectbtn;
WinCircularButton *_circbtn;
public:
WinFacetory() : _rectbtn(NULL), _circbtn(NULL) {} // set rectbtn to null
WinRectButton* getWinRectBtn () {
if(!_rectbtn) _rectbtn = new WinRectButton;
return _rectbtn;
}
WinCircularButton* getWinCircBtn() {
if(!_circbtn) _circbtn = new WinCircularButton;
return _circbtn;
}
~WinFacetory() {
if(_rectbtn) delete _rectbtn;
if(_circbtn) delete _circbtn;
}
};
class AbstractFactory : public WinFacetory, public IOSFacetory {
public:
AbstractFactory(){}
};
in the main function, I'm trying to set a IOSFactory into a AbstractFactory Pointer:
#include "AbstractFactory.h"
int main() {
#ifdef _WIN
AbstractFactory* factory = new WinFacetory;
#else
AbstractFactory* factory = new IOSFacetory;
#endif
std::cin.get();
return 0;
}
It doesn't work and I get the following compilation error:
IntelliSense: a value of type "IOSFacetory *" cannot be used to initialize an entity of type "AbstractFactory *.
I guess I have a minor error but I can't figure it out. I'd like to get helped. thanks!
You should reverse your inheritance relations. AbstractFactory should be a base class of both IOSFactory and WinFactory.
Remember to declare a virtual destructor in the base class.
You should derive WinFacetory and IOSFacetory from AbstractFactory. Now you do it contrariwise.