首先使用的单例设计来自于如何实现单例设计模式?。节目:
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();
}
现在说说我为什么这么做。我有数据库管理器。这适用于单例(在本例中它适用于 sqlite,一个文件,一个连接,单例的完美候选者)。那么为什么是第二个呢?我创建了 PersonDao 来处理 sql 命令,并决定将其设置为单例,尽管我不确定这一决定,但我知道我不会对该 dao 进行子类化,并且我没有看到任何理由为什么要创建多个 dao它在 PersonModel 中的实例(特别是我正在谈论 qt)。无论如何,这只是简化和最小的可重现示例。作为一个实验,并通过该链接的单例设计,有没有办法避免这里的递归性(错误:
terminate called after throwing an instance of '__gnu_cxx::recursive_init_error'
what(): std::exception
Aborted (core dumped)
)?或者唯一的选择就是撤消 dao 的单例模式并创建普通类及其实例?
首先,您不需要在 singleton_2.hpp 文件中包含 singleton_1.hpp,从很多角度来看这是错误的。 person.hpp就足够了。当然,包含 person.hpp 可能会导致问题:重新定义 Person 类。所以根据我的实践经验,你应该在每个头文件中使用#ifndef和#define指令。
示例:
#ifndef MY_PROJECT_SINGLETON_1_HPP
#define MY_PROJECT_SINGLETON_1_HPP
#include "person.hpp"
class Singleton1 {
...
}
#endif
它被称为#include Guard。这不仅可以防止双重声明,还可以防止递归包含。
其次,更好的做法是显式声明在类中存储 Singleton 实例的方式,如下所示:
头文件(.hpp):
class Singleton1 {
public:
...
private:
static Singleton1 singleton1_; // Here
};
不要忘记定义实例
源文件(.cpp):
Singleton1 Singleton1::singleton1_;
这就是您问题的解决方案:
person.hpp:
#ifndef YOUR_PROJECT_PERSON_HPP
#define YOUR_PROJECT_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;
};
#endif //YOUR_PROJECT_PERSON_HPP
人.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:
#ifndef YOUR_PROJECT_SINGLETON_1_HPP
#define YOUR_PROJECT_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;
private:
static Singleton1 singleton1_;
};
#endif //YOUR_PROJECT_SINGLETON_1_HPP
singleton_1.cpp:
#include "singleton_1.hpp"
#include "singleton_2.hpp"
Singleton1 Singleton1::singleton1_;
Singleton1::Singleton1() : person({"William", 45}) {
Singleton2::getInstance().foo();
}
Singleton1& Singleton1::getInstance() {
return singleton1_;
}
const Person& Singleton1::getPerson() const {
return person;
}
singleton_2.hpp:
#ifndef YOUR_PROJECT_SINGLETON_2_HPP
#define YOUR_PROJECT_SINGLETON_2_HPP
#include "person.hpp"
class Singleton2 {
public:
Singleton2(const Singleton2&) = delete;
void operator=(const Singleton2&) = delete;
static Singleton2& getInstance();
void foo() const;
private:
Singleton2();
const Person& person;
private:
static Singleton2 singleton2_;
};
#endif //YOUR_PROJECT_SINGLETON_2_HPP
singleton_2.cpp:
#include "singleton_2.hpp"
#include "singleton_1.hpp"
#include <iostream>
// Definition
Singleton2 Singleton2::singleton2_;
Singleton2::Singleton2():person(Singleton1::getInstance().getPerson()) {}
Singleton2& Singleton2::getInstance() {
return singleton2_;
}
void Singleton2::foo() const {
std::cout << person << std::endl;
}
main.cpp:
#include "singleton_1.hpp"
int main(){
Singleton1::getInstance();
}
结果(在控制台中):
姓名:威廉年龄:45