【问题标题】:Uncopyable object, map and shared_ptr : error in the copy constructor不可复制的对象、映射和 shared_ptr:复制构造函数中的错误
【发布时间】:2016-09-26 00:20:35
【问题描述】:

我在构建不可复制对象时遇到问题。让我们考虑以下示例:

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 是 non-copyable ,它就不起作用。作为指针,我希望我的对象 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>          ]

谢谢。

【问题讨论】:

    标签: c++ dictionary copy shared-ptr copy-constructor


    【解决方案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&amp; 的类型)的左值来满足。但是std::map&lt;std::string, std::shared_ptr&lt;Derived&gt;&gt; 实际上并没有从std::map&lt;std::string, std::shared_ptr&lt;Base&gt;&gt; 继承——这两种类型也根本不相关——std::map 没有交叉类型的构造函数。

    换句话说,仅仅因为 DB 并不意味着 map&lt;X, D&gt;map&lt;X, B&gt;。以这种方式,C++ 类型系统中没有类型的协变。某些类型至少允许您从Class&lt;D&gt;(例如std::shared_ptr)构造Class&lt;B&gt;,但标准容器并非如此(例如vectormap,...)

    您必须将lMap 更改为保留std::shared_ptr&lt;Base&gt;s 才能使其正常工作。它可以在内部保存std::shared_ptr&lt;Derived&gt;s - 但map 类型必须匹配。


    旁注,在 C++11 中,您不需要 Uncopyable。你可以简单地明确delete这些操作:

    A(A const& ) = delete;
    A& operator=(A const& ) = delete;
    

    【讨论】:

    • 我看你的意思,很清楚。因此,如果函数 f 将 std::shared_ptr 作为参数,并且我定义 std::map<:string std::shared_ptr>> lMap。我为 lMap[0] 分配了一个 std::shared_ptr。无法使用 lMap[0] 到 f ?
    • @Canardini 如果f 接受shared_ptr&lt;Derived&gt;,那么您不能将shared_ptr&lt;Base&gt; 传递给它,是的。它怎么知道它实际上指向一个Derived 对象?
    • 对,这就是我从你的回答中了解到的。我尝试使用动态转换指针,它无法解决问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-18
    • 2013-04-03
    • 1970-01-01
    • 2014-07-18
    • 1970-01-01
    相关资源
    最近更新 更多