不可复制的对象、映射和 shared_ptr:复制构造函数中的错误
Uncopyable object, map and shared_ptr : error in the copy constructor
我在构建不可复制的对象时遇到问题。让我们考虑以下示例:
class Uncopyable{
protected:
Uncopyable(){};
~Uncopyable(){};
private:
Uncopyable(const Uncopyable&);
Uncopyable& operator=(const Uncopyable&);
};
class Base { };
class Derived : public Base { };
class A : private Uncopyable {
public:
A(std::map<std::string, std::shared_ptr<Base>> & inMap);
private:
A(const A&);
A& operator=(const A&);
};
int main() {
std::map<std::string, std::shared_ptr<Derived>> lMap;
std::shared_ptr<A> oA(std::make_shared<A>(lMap));
}
如果我假设我的对象 A 是不可复制的,它不是 work.As 指针,我希望我的对象 A 理解 Derived 是一个 Base,但我收到以下消息:
error C2664: 'A::A(const A &)' : cannot convert argument 1 from 'std::map<std::string,std::shared_ptr<Derived>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>' to 'std::map<std::string,std::shared_ptr<Base>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>> &'
1> with
1> [
1> _Kty=std::string
1> , _Ty=std::shared_ptr<Derived>
1> ]
1> and
1> [
1> _Kty=std::string
1> , _Ty=std::shared_ptr<Base>
1> ]
谢谢。
该错误与 A
的不可复制性无关,实际上不在复制构造函数中 - 它在 map
构造函数中。该错误与 A'
构造函数采用
这一事实有关
std::map<std::string, std::shared_ptr<Base>> &
你正在传递一个:
std::map<std::string, std::shared_ptr<Derived>>
作为类型 T
的左值引用的参数只能由类型 T
或从 T
派生的类型(或具有一个 operator T&
)。但是 std::map<std::string, std::shared_ptr<Derived>>
实际上并没有从 std::map<std::string, std::shared_ptr<Base>>
继承——这两种类型也根本不相关——std::map
没有跨类型的构造函数。
换句话说,仅仅因为 D
是 B
并不意味着 map<X, D>
是 map<X, B>
。以这种方式,在 C++ 类型系统中没有类型协变。某些类型至少允许您从 Class<D>
构建 Class<B>
(例如 std::shared_ptr
),但标准容器并非如此(例如 vector
、map
, ...)
您必须将 lMap
更改为保持 std::shared_ptr<Base>
s 才能使其正常工作。它可以在内部保存 std::shared_ptr<Derived>
s - 但 map
类型必须匹配。
旁注,在 C++11 中您不需要 Uncopyable
。您可以简单地显式 delete
这些操作:
A(A const& ) = delete;
A& operator=(A const& ) = delete;
我在构建不可复制的对象时遇到问题。让我们考虑以下示例:
class Uncopyable{
protected:
Uncopyable(){};
~Uncopyable(){};
private:
Uncopyable(const Uncopyable&);
Uncopyable& operator=(const Uncopyable&);
};
class Base { };
class Derived : public Base { };
class A : private Uncopyable {
public:
A(std::map<std::string, std::shared_ptr<Base>> & inMap);
private:
A(const A&);
A& operator=(const A&);
};
int main() {
std::map<std::string, std::shared_ptr<Derived>> lMap;
std::shared_ptr<A> oA(std::make_shared<A>(lMap));
}
如果我假设我的对象 A 是不可复制的,它不是 work.As 指针,我希望我的对象 A 理解 Derived 是一个 Base,但我收到以下消息:
error C2664: 'A::A(const A &)' : cannot convert argument 1 from 'std::map<std::string,std::shared_ptr<Derived>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>' to 'std::map<std::string,std::shared_ptr<Base>,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>> &'
1> with
1> [
1> _Kty=std::string
1> , _Ty=std::shared_ptr<Derived>
1> ]
1> and
1> [
1> _Kty=std::string
1> , _Ty=std::shared_ptr<Base>
1> ]
谢谢。
该错误与 A
的不可复制性无关,实际上不在复制构造函数中 - 它在 map
构造函数中。该错误与 A'
构造函数采用
std::map<std::string, std::shared_ptr<Base>> &
你正在传递一个:
std::map<std::string, std::shared_ptr<Derived>>
作为类型 T
的左值引用的参数只能由类型 T
或从 T
派生的类型(或具有一个 operator T&
)。但是 std::map<std::string, std::shared_ptr<Derived>>
实际上并没有从 std::map<std::string, std::shared_ptr<Base>>
继承——这两种类型也根本不相关——std::map
没有跨类型的构造函数。
换句话说,仅仅因为 D
是 B
并不意味着 map<X, D>
是 map<X, B>
。以这种方式,在 C++ 类型系统中没有类型协变。某些类型至少允许您从 Class<D>
构建 Class<B>
(例如 std::shared_ptr
),但标准容器并非如此(例如 vector
、map
, ...)
您必须将 lMap
更改为保持 std::shared_ptr<Base>
s 才能使其正常工作。它可以在内部保存 std::shared_ptr<Derived>
s - 但 map
类型必须匹配。
旁注,在 C++11 中您不需要 Uncopyable
。您可以简单地显式 delete
这些操作:
A(A const& ) = delete;
A& operator=(A const& ) = delete;