如何在C++中调用另一个单例中的单例方法?

问题描述 投票:0回答:1

首先使用的单例设计来自于如何实现单例设计模式?。节目:

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 的单例模式并创建普通类及其实例?

c++ design-patterns singleton
1个回答
0
投票

首先,您不需要在 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

© www.soinside.com 2019 - 2024. All rights reserved.