Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用智能指针复制构造函数_C++_Templates_Smart Pointers_Copy Constructor - Fatal编程技术网

C++ 使用智能指针复制构造函数

C++ 使用智能指针复制构造函数,c++,templates,smart-pointers,copy-constructor,C++,Templates,Smart Pointers,Copy Constructor,我有一个类,有一个std::unique\u ptr作为类成员。我想知道如何正确定义复制构造函数,因为我收到了以下编译器错误消息:错误C2248:std::unique\u ptr::unique\u ptr:无法访问类“std::unique\u ptr”中声明的私有成员。我的课堂设计看起来像: template <typename T> class Foo{ public: Foo(){}; Foo( Bar<T> *, int

我有一个类,有一个
std::unique\u ptr
作为类成员。我想知道如何正确定义复制构造函数,因为我收到了以下编译器错误消息:
错误C2248:std::unique\u ptr::unique\u ptr:无法访问类“std::unique\u ptr”中声明的私有成员。我的课堂设计看起来像:

template <typename T>
class Foo{
    public:
        Foo(){};
        Foo( Bar<T> *, int );
        Foo( const Foo<T> & );
        ~Foo(){};

        void swap( Foo<T> & );
        Foo<T> operator = ( Foo<T> );

    private:
        std::unique_ptr<Bar> m_ptrBar;
        int m_Param1;

};

template < typename T >
Foo<T>::Foo( const Foo<T> & refFoo )
:m_ptrBar(refFoo.m_ptrBar), 
m_Param1(refFoo.m_Param1)
{
    // error here!
}

template < typename T >
void Foo<T>::swap( Foo<T> & refFoo ){
    using std::swap;
    swap(m_ptrBar, refFoo.m_ptrBar);
    swap(m_Param1, refFoo.m_Param1);
 }

 template < typename T >
 Foo<T> Foo<T>::operator = ( Foo<T> Elem ){
    Elem.swap(*this);
    return (*this);
 }
模板
福班{
公众:
Foo(){};
Foo(Bar*,int);
富(常富&);
~Foo(){};
无效掉期(Foo&);
Foo运算符=(Foo);
私人:
std::唯一的\u ptr m\u ptrBar;
int m_Param1;
};
模板
Foo::Foo(const Foo和refFoo)
:m_ptrBar(refFoo.m_ptrBar),
m_参数1(参考foo.m_参数1)
{
//这里出错了!
}
模板
void Foo::swap(Foo和refFoo){
使用std::swap;
交换(m_ptrBar,refFoo.m_ptrBar);
交换(m_Param1,refFoo.m_Param1);
}
模板
Foo-Foo::operator=(Foo-Elem){
要素互换(*本);
返回(*本条);
}

假设目标是复制并构造唯一拥有的条形图

template < typename T >
Foo<T>::Foo( const Foo<T> & refFoo )
: m_ptrBar(refFoo.m_ptrBar ? new Bar(*refFoo.m_ptrBar) : nullptr),
  m_Param1(refFoo.m_Param1)
{
}
模板
Foo::Foo(const Foo和refFoo)
:m_ptrBar(refFoo.m_ptrBar?新条(*refFoo.m_ptrBar):nullptr),
m_参数1(参考foo.m_参数1)
{
}

独特的ptr文档:

Stores a pointer to an owned object. The object is owned by no other unique_ptr. 
The object is destroyed when the unique_ptr is destroyed.
您不能复制它,因为两个对象不能拥有它

尝试切换到std::shared\u ptr


编辑我应该指出,这将使两个对象都有指向同一对象的指针。如果要复制唯一拥有的对象,Cubbi的解决方案是正确的。

可以为此创建一个新的
克隆类型

下面是一个调用派生对象的正确复制构造函数(和析构函数)的
克隆ptr
的基本示例。这是通过在创建
clone\u ptr
时创建一个“type erasure”助手来完成的

其他的实现可以在互联网上找到

#include <memory>

namespace clone_ptr_detail
{
template <class T>
class clone_ptr_helper_base
{
public:
    virtual ~clone_ptr_helper_base() {}
    virtual T* clone(const T* source) const = 0;
    virtual void destroy(const T* p) const = 0;
};

template <class T, class U>
class clone_ptr_helper: public clone_ptr_helper_base<T>
{
public:
    virtual T* clone(const T* source) const
    {
        return new U(static_cast<const U&>(*source));
    }
    virtual void destroy(const T* p) const
    {
        delete static_cast<const U*>(p);
    }
};
}

template <class T>
class clone_ptr
{
    T* ptr;
    std::shared_ptr<clone_ptr_detail::clone_ptr_helper_base<T>> ptr_helper;
public:
    template <class U>
    explicit clone_ptr(U* p): ptr(p), ptr_helper(new clone_ptr_detail::clone_ptr_helper<T, U>()) {}

    clone_ptr(const clone_ptr& other): ptr(other.ptr_helper->clone(other.ptr)), ptr_helper(other.ptr_helper) {}

    clone_ptr& operator=(clone_ptr rhv)
    {
        swap(rhv);
        return *this;
    }
    ~clone_ptr()
    {
        ptr_helper->destroy(ptr);
    }

    T* get() const { /*error checking here*/ return ptr; }
    T& operator* () const { return *get(); }
    T* operator-> () const { return get(); }

    void swap(clone_ptr& other)
    {
        std::swap(ptr, other.ptr);
        ptr_helper.swap(other.ptr_helper);
    }
};
#包括
名称空间克隆\u ptr\u详细信息
{
模板
类clone\u ptr\u helper\u base
{
公众:
虚拟~clone\u ptr\u helper\u base(){}
虚拟T*克隆(常数T*源)常数=0;
虚空破坏(常数T*p)常数=0;
};
模板
类clone\u ptr\u helper:public clone\u ptr\u helper\u base
{
公众:
虚拟T*克隆(常量T*源)常量
{
返回新U(静态_转换(*源));
}
虚空破坏(常数T*p)常数
{
删除静态_-cast(p);
}
};
}
模板
类克隆\u ptr
{
T*ptr;
std::共享ptr ptr\u助手;
公众:
模板
显式克隆ptr(U*p):ptr(p),ptr_助手(新克隆ptr_细节::克隆ptr_助手()){}
clone_ptr(const clone_ptr&other):ptr(other.ptr_helper->clone(other.ptr)),ptr_helper(other.ptr_helper){}
clone_ptr&operator=(clone_ptr rhv)
{
互换(rhv);
归还*这个;
}
~clone_ptr()
{
ptr_helper->销毁(ptr);
}
T*get()常量{/*此处检查错误*/return ptr;}
T运算符*()常量{return*get();}
T*运算符->()常量{return get();}
无效交换(克隆ptr和其他)
{
标准::交换(ptr,other.ptr);
ptr_helper.swap(其他.ptr_helper);
}
};
请参阅用法示例:


(但也许你真的不需要复制你的对象,而应该探索移动语义的可能性。例如,你可以有一个
向量
,只要你不使用复制内容的函数。)

@Cubbi,谢谢。我现在有另一个问题。
Bar
类实际上是一个抽象基类,因此我收到一条新的错误消息:
错误C2259:“Bar”:无法实例化抽象类
,除了将抽象基类转换为简单基类之外,还有什么解决方案吗?@Tin:在这种情况下,您需要添加一个纯虚拟的
克隆()
函数调用基类,在每个派生类中重写以使用
new
创建副本。然后初始化器变成
bar(foo.bar?foo.bar->clone():nullptr)
@Tin如果我现在有一个私有成员的类,C++FAQ调用@MikeSeymour@Cubbi:
std::vector mvector,并且要定义复制构造函数和赋值运算符,那么我需要逐个元素地复制调用
“clone()”虚拟函数的元素,对吗?因为如果我遵循参数化列表中复制构造函数的传统实现,即
MyCollection::mycollecyon(const refCol):myvector(refCol.myvector){}
,我会得到一个编译器错误。@Cubbi,如果现在我只想
std::move
指针呢?我尝试了一些东西,比如
muptrbar(std::move(refFoo.m\u ptrBar))
,但没有成功。有什么建议吗?@w00te,谢谢。还有一个问题。如果Bar类实际上是一个抽象基类呢?我收到一条新的错误消息:
错误C2259:'Bar':无法实例化抽象类
。除了将抽象基类转换为简单基类之外,还有什么解决方案吗?Cubbi的解决方案创建了一个新的Bar对象,该对象将包含在新类中的unique_ptr中。若bar是抽象的,那个么它就不能工作——它必须创建一个适用派生类的新对象。您必须添加逻辑才能实现这一点。