gpt4 book ai didi

c++ - 使用命名空间而不是单例

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:00:23 25 4
gpt4 key购买 nike

最近我在 SO 上发布了一个关于类的使用的问题,该类带有一些理想情况下应该具有的独立功能。我被推荐学习单例模式,这样只有一个类的实例被创建,并且它管理围绕它封装的数据的一组操作。您可以在此处查看问题 - using Static Container for base and derived classes .


现在考虑这段代码 -

#include <iostream>
#include <string>
#include <unordered_map>

class A{
std::string id;
public:
A(std::string _i): id(_i){}
virtual void doSomething(){std::cout << "DoSomethingBase\n";}
};

class B : public A{
std::string name;
public:
B(std::string _n):name(_n), A(_n){}
void doSomething(){std::cout << "DoSomethingDerived\n";}
};

namespace ListA{
namespace{
std::unordered_map<std::string, A*> list;
}
void init(){
list.clear();
}
void place(std::string _n, A* a){
list[_n] = a;
}
}


int main() {
ListA::init();
ListA::place("b1", new B("b1"));
ListA::place("a1", new A("a1"));
return 0;
}

忽略了我仍在使用原始指针的事实,如果程序没有按原样终止,它们会泄漏内存,这是使用全局静态变量或单例的一个很好的替代方法吗?


关于前面的问题,我重新组织了 A 类(基类)和 B 类(派生类),独立于管理这些对象列表的命名空间。那么这是一个好主意,还是一个完全糟糕的做法?有什么缺点吗?

我被建议的一个很好的单例实现如下 -

class EmployeeManager
{
public:
static EmployeeManager& getInstance()
{
static EmployeeManager instance; // Guaranteed to be destroyed.
// Instantiated on first use.
return instance;
}
private:
EmployeeManager() {};
std::unordered_map<std::string, Employee&> list;
public:
EmployeeManager(EmployeeManager const&) = delete;
void operator=(const&) = delete;
void place(const std::string &id, Employee &emp){
list[id] = emp;
}
};

class Employee
{
public:
virtual void doSomething() = 0;
};

class Writer : public Employee
{
private:
std::string name_;
public:
Writer(std::string name) : name_(name) {};
void doSomething() { };
};

老实说,我从来没有尝试过单例模式,我也不敢直接使用它,因为我之前没有任何经验,我宁愿先在我喜欢的项目中使用它。

最佳答案

is this a good alternative to using global static variables, or a singleton?

不,因为您可能会遇到另一个问题:static initialization order fiasco .有一些方法可以修复它——但是使用带有静态变量的函数——它看起来就像单例。

...但是为什么需要全局变量(即使在命名空间中)或单例?在您的第一个示例中,如果您使用 struct ListA 而不是 namespace ListA 就完全没问题了 - 并删除该 namespace{。那么你有:

int main() {
ListA list;
list.init();
list.place("b1", new B("b1"));
list.place("a1", new A("a1"));
}

看起来不错。

然后你的单例方法,再一次 - 不需要它 - 在你的主函数中创建 EmployeeManager 类型的变量,如果你需要在其他类中使用它,然后通过引用传递它或指针。

关于c++ - 使用命名空间而不是单例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39335478/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com