出于教育目的,我今天早些时候实现了一个包装类,定义如下(这取自一本书):
#ifndef WRAPPER_H
#define WRAPPER_H
template<class T>
class Wrapper
{
public:
Wrapper()
{ dataPtr = 0; }
Wrapper(const T& inner)
{
dataPtr = inner.clone();
}
Wrapper(const Wrapper<T> &original)
{
if (original.dataPtr != 0)
dataPtr = original.dataPtr->clone();
else
dataPtr = 0;
}
Wrapper &operator =(const Wrapper<T> &original)
{
if (this != &original)
{
if (dataPtr != 0)
delete dataPtr;
dataPtr = (original.dataPtr !=0) ? original.dataPtr->clone() : 0;
}
return *this;
}
~Wrapper()
{
if (dataPtr != 0)
delete dataPtr;
}
T &operator*()
{
return *dataPtr;
}
const T&operator*() const
{
return *dataPtr;
}
T *operator->()
{
return dataPtr;
}
const T * const operator->() const
{
return dataPtr;
}
private:
T *dataPtr;
};
#endif
主要思想是充当指针,具有处理内存管理,复制构造函数,析构函数和赋值运算符的额外优势。它包装了具有克隆方法的类:它们返回指向自身副本的指针(不是指向自己,指向使用new
Class(*this)
制作的新副本)。
在某些方面,它似乎像unique_ptr
,因为包装的对象只能通过此包装器访问。但是,有一点不同,这就是我的问题所在。在这个包装类中,有一个构造函数,它通过接受对它包装的类的对象的引用(上面代码中的第一个构造函数)来定义。
这很方便。假设我们有A
和B
类,B
的构造函数会引用Wrapper< A >
。然后我可以用另一个对象B
构建一个对象A
:
A object1;
B object2(A);
这是因为object2
用于使用前面提到的Wrapper< A >
构造函数构造B
(然后传递给Wrapper
的构造函数)。
是否可以使用std::memory
中的任何智能指针执行此操作?我的主要目标是教育,但在实践中我不想重新发明轮子。
答案 0 :(得分:5)
智能指针旨在提供所有权语义,可以对其进行分类(并使用可用的c ++标准实现):
这与你的包装器实现完全不同。
答案 1 :(得分:1)
是的,所有这一切都是可能的..以供参考..因为一旦我也实现了类似的东西..(出于教育目的)..我可以分享我为smartpointer制作的代码,引用计数..这意味着您可以根据需要创建任意数量的副本,当最后一个副本被销毁时,它将删除该对象
#ifndef UberPointer
#define UberPointer UPointer
template <class UClass> class UPointer
{
private:
struct UPointerRef
{
UClass* pObject;
int _nCount;
UPointerRef(UClass* pRef){_nCount=0;pObject = pRef;}
~UPointerRef(){if(pObject)delete pObject;}
void AddRef(void){++_nCount;}
void RemoveRef(void){if (--_nCount <= 0){delete this;}}
};
UPointerRef* _pRef;
public:
UPointer()
{
_pRef = new UPointerRef(0x0);
_pRef->AddRef();
}
UPointer(UClass* pPointer)
{
_pRef = new UPointerRef(pPointer);
_pRef->AddRef();
}
UPointer(UPointer<UClass> &oPointer)
{
_pRef = oPointer._pRef;
_pRef->AddRef();
}
~UPointer(void)
{
_pRef->RemoveRef();
}
UClass* GetObject()
{
ASSERT(_pRef->pObject);
return _pRef->pObject;
}
operator UClass*(void)
{
ASSERT(_pRef->pObject);
return _pRef->pObject;
}
UClass& operator*(void)
{
ASSERT(_pRef->pObject);
return *(_pRef->pObject);
}
UClass* operator->(void)
{
ASSERT(_pRef->pObject);
return (_pRef->pObject);
}
UPointer& operator=(UPointer<UClass> &oPointer)
{
_pRef->RemoveRef();
_pRef = oPointer._pRef;
_pRef->AddRef();
return *this;
}
UPointer& operator=(UClass* pPointer)
{
_pRef->RemoveRef();
_pRef = new UPointerRef(pPointer);
_pRef->AddRef();
return *this;
}
bool operator==(UClass* pPointer)
{
return _pRef->pObject == pPointer;
}
bool operator!=(UClass* pPointer)
{
return _pRef->pObject != pPointer;
}
bool operator !(void)
{
return (_pRef->pObject == 0x0);
}
operator bool(void)
{
return (_pRef->pObject != 0x0);
}
};
#endif
答案 2 :(得分:1)
A object1;
B object2(A);
是否可以使用std :: memory中的任何智能指针执行此操作?
使用标准智能指针,您将无法获得深层复制语义。您将具有浅复制语义(使用std :: shared_ptr)或移动语义(使用std :: unique_ptr)。但是,没有什么可以阻止您在类中创建返回智能指针的clone()
方法。这样,您可以在需要时获得深层副本,同时仍然可以从智能指针附带的所有权语义中受益。