2017-02-02 15 views
2

に、私は以前の今日(これは本から取られる)の下に定義されたラッパークラスを実装した教育目的のための単純なラッパークラス対スマートポインタ

#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 

主なアイデアは、ポインタとして機能することですメモリ管理、コピーコンストラクタ、デストラクタ、代入演算子の世話をするという利点があります。これは、クローンメソッドを持つクラスをラップします。つまり、自身のコピーではなく、newClass(*this)で作成された新しいコピーへのポインタを返します。

いくつかの点では、ラップされたオブジェクトはこのラッパーを介してのみアクセス可能であるため、unique_ptrのように見えます。しかし、それは私の質問についてですが、違いがあります。このラッパークラスには、ラップするクラスのオブジェクトへの参照を受け入れることによって定義されたコンストラクターがあります(上記のコードの最初のコンストラクター)。

これは非常に便利です。クラスABがあり、BのコンストラクタではWrapper<A>という参照があるとします。 object2は、上記Wrapperコンストラクタを使用してWrapper<A>(その後Bのコンストラクタに渡された)を構築するために使用されているためである

A object1; 
B object2(A); 

:私は別のオブジェクトAとオブジェクトBを構築することができます。

std::memoryのスマートポインタでこれを行うことはできますか?ここで私の主な目標は教育ですが、実際には私は車輪を再構築したくありません。

+1

コピーコンストラクタは、コピー後も一意ではなくなるため、一意のポインタには使用できません。共有ポインタは代わりに_copyable_です。ここでは、コピーは単にポイントオブジェクトの所有権を共有しているという事実を強制しています。 – skypjack

+0

これは、ポインタを共有/移動するのではなく、深いコピーを実行しているようです。 – user4581301

+0

intrusive_ptrのように見えます –

答えて

5

所有セマンティクスを提供することを目的とスマートポインタ、とすることができますカテゴリ化されています(利用可能なC++の標準実装にあります):

  • ユニーク
  • の周りに渡されたときに所有権が常に単一の所有者はありませんを共有し、スマートポインタは参照をカウントし、これらの秋ならば0
  • 弱いにdeceases転送され、従属ポインタですが、参照ポインタがまだ有効かどうかを確認する機能を提供します。

これはラッパーの実装とはまったく異なります。

1

はいすべてのことが可能です。参考にして、私も同じようなものを実装しています。(教育的目的のためにも)..リファレンスカウントでスマートポインタのために作ったコードを共有できます。 。あなたが望むようにのように多くのコピーを作成することができることを意味し、最後のコピーが破壊されたとき、それは、オブジェクトを削除すること

#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 
+1

あなたはルールに違反しているようには見えませんが、とにかくここにドロップします:[C++識別子でアンダースコアを使用するルールは何ですか?](http://stackoverflow.com/questions/228783/what -All-the-using-an-a-identifier) – user4581301

+0

ええと...何年もの間、私は自分の種類の表記法を開発し始めました.C++スタンドアールではありませんが、クロスです(C#/ javascript/SQL)..それは、あなたが移動するたびに適応の歪みを軽減します。 – CaldasGSM

+0

命名規則は良いです。もの。ニーモニックやヒントとして多くのプレフィックスと接尾辞を使用しています。下線付きの心配は、あなたが誤って標準ライブラリの実装が所有する名前を使用して、コンパイラのエラーや本当に奇妙なランタイム結果を得る可能性があることです。 – user4581301

1
A object1; 
B object2(A); 

それがのstd ::メモリ内のスマートポインタのいずれかでこれを行うことは可能ですか?

標準のスマートポインタでは、ディープコピーセマンティクスを取得できません。あなたは、浅いコピーのセマンティクス(std :: shared_ptr)または移動セマンティクス(std :: unique_ptr)を持つでしょう。ただし、スマートポインタを返すクラスにclone()メソッドを作成することはできません。こうすることで、スマートポインタに付属する所有権セマンティクスの恩恵を受けながら、必要なときに深いコピーを作成することができます。

関連する問題