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