std :: map和私有构造函数

时间:2016-05-12 10:24:11

标签: c++

这是一个没有编译的代码:

#include <map>
using namespace std;

class A;

class B {
        friend class A;
        int b;
        B():b(1){};
        B(int b_):b(b_){};
};

class A {
        map<int,B> objects;
public:
        void init(){
              objects[2]=B(3);
        }
};

int main(){
        A a;
        a.init();
        return 0;
}

根据我在错误消息中的理解:

/usr/include/c++/4.8/bits/stl_map.h: In instantiation of ‘std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = int; _Tp = B; _Compare = std::less<int>; _Alloc = std::allocator<std::pair<const int, B> >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = B; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = int]’:
foo.cc:18:24:   required from here
foo.cc:9:10: error: ‘B::B()’ is private
          B():b(1){};
          ^
In file included from /usr/include/c++/4.8/map:61:0,
                 from foo.cc:1:
/usr/include/c++/4.8/bits/stl_map.h:469:59: error: within this context
           __i = insert(__i, value_type(__k, mapped_type()));
                                                           ^

问题是&#34; map&#34;不是B的朋友,因此它可能不会使用构造函数B()(顺便提一下,我注意到objects[2]=B(3);需要B()!)。

我找到了以下解决方法:

objects.insert(pair<int,B>(2,B(3)));

有效......直到~B()也是私有的。

那么,当B的构造函数和析构函数是私有的时,有没有办法在A内构建B的地图?

其他问题:为什么objects[2]=B(3);使用B()

2 个答案:

答案 0 :(得分:3)

严格来说,这不是你问题的答案,但我认为它能以更优雅的方式解决你的问题。

不要将B的所有字段设为私有,然后在A中弄乱朋友关键字,您可以将B类隐藏在外部世界中,使其成为私有member class

#include <map>

class A {
    class B {
        int b;

       public:
        B() : b(1){};
        B(int b_) : b(b_){};
        ~B() {}
    };
    std::map<int, B> objects;

   public:
    void init() {
        auto b = B();
        objects[2] = B(3);
        objects.insert(std::pair<int, B>(2, B(3)));
    }
};

int main() {
    A a;
    A::B b; // 'A::B': cannot access private class declared in class 'A'
    a.init();
    return 0;
}

这样你仍然不能在A之外自由地构造B,但是A可以以任何方式使用它。这也解锁了B中更精细的封装粒度:某些部分可以被私有/保护免受A.友情类代码不是这种情况。

示意图,您可以将代码视为:

 A [ B [ private(a), private(b), private(c), ... ] ]

虽然我的代码更像是:

 A[ private(B[a, b, c]) ]

即。私有性是“B”的“因素”

答案 1 :(得分:1)

看一下这个链接http://www.cplusplus.com/reference/map/map/operator[]/,它说

  

对此功能的调用相当于:

(*((this->insert(make_pair(k,mapped_type()))).first)).second

默认构造函数是从类std::map范围内调用的,该范围不是此类的朋友。因此错误。

错误应该存在。这样的构造函数不应该被声明为私有。

解决此问题的另一种方法是将对象的构造委托给类A,并将指针(或引用包装器)的整数映射到B.这个映射应该只能访问通过A暴露的接口。这样,B对象的整个生命周期都由A管理,并且没有不变量被破坏。