带私有构造函数的C ++静态列表

时间:2014-08-19 01:26:40

标签: c++ static friend access-control private-constructor

如果有人问我,我很抱歉,我不确定如何用最好的词来表达它。

我本质上有一个类,我想维护一个自己的地图,该列表应该只有对象的实例化。

using std::unordered_map;
class MyClass
{
    ~MyClass() {};
    MyClass() {};   // these actually contain code which operate on the classes data
    static unordered_map<Uint32, MyClass> list;
public:
    static const MyClass& GetObject(Uint32 key) {return list[key];};

};

当我编译我的代码时,它基本上给了我一堆来自STL的错误,说它调用了删除的函数等等,这是有道理的,因为unordered_map可能使用构造函数和析构函数,所以我声明unordered_map是朋友< / p>

friend class unordered_map<Uint32, MyClass>;

然而,似乎没有更少的错误,我推测这是由于unordered_map(如pair)和hash使用的类。所以我的问题是,如果有替代方案。我是否应该向编译器声明出现错误的朋友,或者是否有其他方法?

2 个答案:

答案 0 :(得分:2)

因此。你有兴趣做一些烦人的事情。所以我们这样做吧。正如AlexD所说,你所缺少的是一个公共析构函数。 unordered_map需要访问它(可能通过一些实现定义的内部类)。

所以,让我们这样做,让我们做你应该做的事情,那就是做一个更小更简单的测试用例:

#include <unordered_map>

class MyClass {
    public:
        ~MyClass() {}

    private:
        MyClass() {}
};

int main() {
    std::unordered_map<int, MyClass> x;
    x.at(3);
    //x[3];
}

Now that compiles fine

现在,请注意我已注释掉x[3]。我们不能使用它。那是因为如果地图中不存在3,我们会调用MyClass的默认构造函数,它是私有的。并且因为编译器在编译时不知道是否为真,所以需要确保它可以调用构造函数。


从评论中可以看出,您无法在此地图中插入任何对象。好吧,让我们添加一个静态工厂方法并摆脱这个问题:

#include <unordered_map>
using std::unordered_map;

class MyClass {
    public:
        static MyClass factory() { return MyClass(); }
        ~MyClass() {}

    private:
        MyClass() {}
        int x;
};

int main() {
    std::unordered_map<int, MyClass> x;
    x.insert(std::make_pair(3, MyClass::factory()));
    x.emplace(4, MyClass::factory());
}

答案 1 :(得分:1)

更新:T.C。我特别指出了一些我忽略的事情,所以这个答案完成了一个完整的面孔......

#include <iostream>
#include <unordered_map>
#include <map>
#include <cinttypes>

class MyClass
{
    typedef std::unordered_map<uint32_t, MyClass> Instances;
    friend Instances;
    friend std::pair<uint32_t, MyClass>;
    friend std::pair<const uint32_t, MyClass>;
  public:
    static const MyClass& getObject(uint32_t key) { return instances_[key] = 2 * key; }
    ~MyClass() {}
    int n() const { return n_; }
  private:
    MyClass() : n_(-1) { }
    MyClass& operator=(int n) { n_ = n; return *this; }
    int n_;
    static Instances instances_;
};

MyClass::Instances MyClass::instances_;

int main() {
    const MyClass& m20 = MyClass::getObject(20);
    const MyClass& m21 = MyClass::getObject(21);
    std::cout << m20.n() << ' ' << m21.n() << '\n';
}

以上代码at ideone.com

根据评论,标准没有记录必要的友谊列表,因此可能会破坏新的编译器版本或移植到另一个编译器。

Alterantively,您可以在unordered_map中存储(智能)指针。