vendredi 13 octobre 2023

How to call singleton method inside another singleton in C++?

First the design of singletons used are from How do you implement the Singleton design pattern?. The program:

person.hpp:

#include <string>
#include <ostream>

class Person {
public:
    Person(const std::string& name, int age);

    friend std::ostream& operator<<(std::ostream& os, const Person& person);

private:
    std::string name;
    int age;
};

person.cpp:

#include "person.hpp"

Person::Person(const std::string& name, int age) : name(name), age(age) {}

std::ostream& operator<<(std::ostream& os, const Person& person) {
    os << "name: " << person.name << " age: " << person.age;
    return os;
}

singleton_1.hpp:

#include "person.hpp"

class Singleton1 {
public:
    Singleton1(const Singleton1&) = delete;

    void operator=(const Singleton1&) = delete;

    static Singleton1& getInstance();

    const Person& getPerson() const;

private:
    Singleton1();

    Person person;
};

singleton_1.cpp:

#include "singleton_1.hpp"

#include "singleton_2.hpp"

Singleton1::Singleton1() : person({"William", 45}) {
    Singleton2::getInstance().foo(); // calling this from second singleton, causes __gnu_cxx::recursive_init_error
}

Singleton1& Singleton1::getInstance() {
    static Singleton1 s;
    return s;
}

const Person& Singleton1::getPerson() const {
    return person;
}

singleton_2.hpp:

#include "singleton_1.hpp"

class Singleton2 {
public:
    Singleton2(const Singleton2&) = delete;
    void operator=(const Singleton2&) = delete;
    static Singleton2& getInstance();
    void foo() const;
private:
    Singleton2();
    const Person& person;
};

singleton_2.cpp:

#include "singleton_2.hpp"

#include <iostream>

Singleton2::Singleton2():person(Singleton1::getInstance().getPerson()) {}

Singleton2& Singleton2::getInstance() {
    static Singleton2 s;
    return s;
}

void Singleton2::foo() const {
    std::cout << person << std::endl;
}

main.cpp:

#include "singleton_1.hpp"

int main(){
    Singleton1::getInstance();
}

Now as to why I have done this. I had database manager. Which is appropriate for singleton (in this case it was for sqlite, one file, one connection, perfect candidate for singleton). And so why the second one? I made PersonDao for handling sql commands and decided to make it singleton as well even though I was not sure about that decision, but I knew that I am not going to subclass that dao and I have not seen any reason why to create more then one instance of it in PersonModel (specifically I am talking about qt). Anyway this is just simplification and minimal reproducible example. Taken as an experiment, and with singleton design from that link, is there a way to avoid the recursivness here (error:

terminate called after throwing an instance of '__gnu_cxx::recursive_init_error'
  what():  std::exception
Aborted (core dumped)

)? Or is the only option just undo singleton pattern for dao and make normal class and instances of it?

Aucun commentaire:

Enregistrer un commentaire