std::映射和私有构造函数
std::map and private constructor
这里有一个不编译的代码:
#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()));
^
问题是"map"不是B
的朋友,所以它可能不会使用构造函数B()
(顺便说一句,我注意到objects[2]=B(3);
需要B()
!)。
我找到了以下解决方法:
objects.insert(pair<int,B>(2,B(3)));
哪个有效。。。直到CCD_ 5也是私有的。
那么,当B
的构造函数和析构函数是私有的时,有没有办法在A
内部构建B
的映射?
附加问题:为什么objects[2]=B(3);
使用B()
?
严格来说,它不是你问题的答案,但我认为它以一种更优雅的方式解决了你的问题。
与其把B的所有字段都设为私有字段,然后在A中篡改friend关键字,不如把B类设为私有成员类来向外界隐藏:
#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 中
看看这个链接http://www.cplusplus.com/reference/map/map/operator[]/,上面写着
对该函数的调用相当于:
(*((this->insert(make_pair(k,mapped_type()))).first)).second
默认构造函数是从类std::map
的作用域内调用的,该作用域不是该类的朋友。因此出现了错误。
错误应该存在。这样的构造函数不应该被声明为私有的。
解决这个问题的另一种方法是将对象的构造委托给类A
,并具有指向B的指针(或引用包装器)的整数映射。然后,该映射应该只能通过A
公开的接口访问。这样,B
对象的整个生命周期都由A
管理,并且不会破坏不变量。
相关文章:
- std::映射,只有move构造函数可用
- 重载调用是不明确的:一对内联映射作为构造函数参数
- 映射构造函数,同时在C++中实现计数器
- 在类构造函数中初始化映射时,如何避免内存泄漏
- 如何将映射从类构造函数传递到类中的另一个函数
- C++构造函数期间向映射添加"self"
- SWIG 多参数类型映射适用于函数,但如果有多个构造函数,则不适用于构造函数
- 具有私有构造函数和自身静态容器(映射)的对象
- 多映射插入键类型信息 std::make_pair vs std::p air 构造函数
- 不可复制的对象、映射和shared_ptr:复制构造函数中出错
- C++将带有构造函数的对象插入到映射中
- 为什么映射上的std::for_each调用复制构造函数
- 缺少用于映射初始化的构造函数
- 为什么我的结构中映射的构造函数不起作用
- 具有带参数的构造函数的自定义类的映射
- std::映射和私有构造函数
- 如何使用move构造函数正确处理shared_ptr的映射
- 试图初始化将对象作为构造函数内值的映射
- 通过引用将 std::map 传递给不更新映射的类的构造函数
- c++构造函数映射对象(已编辑)