1

Queueというクラス テンプレートを作成しましたが、タイプとして Worker という別のクラスへのポインタを使用してインスタンス化しようとすると問題が発生します。Queue<Worker*>

問題は、この具体的な Queue メソッドにあると思います。

// Add item to queue
template <typename Type>
bool Queue<Type>::enqueue(const Type& item)
{
    if (isfull())
        return false;
    Node* add = new Node; // create node
    // on failure, new throws std::bad_alloc exception
    add->item = item; // set node pointers (shallow copying!!!!!)
    add->next = nullptr;
    items++;
    if (front == nullptr) // if queue is empty,
        front = add; // place item at front
    else
        rear->next = add; // else place at rear
    rear = add; // have rear point to new node
    return true;
}

型パラメーターがポインターの場合、プログラムのクラッシュを避けるために、アドレスではなく、ポイント先の値をコピーする必要があります (動的メモリ管理を使用しています)。

テンプレートでこれを解決する方法がわかりません。

何か助けはありますか?

4

2 に答える 2

2

特性テクニックを使用します。

つまり、すべての魔法が実装される単純な構造体を定義します。この deep_copy のようなもの:

  template <typename T>
  struct deep_copy {
     void do_copy(T& d, const T& s)
     {
        d = s;
     }
  };

ポインタの特殊化

   template <typename T>  
   struct deep_copy<T*> {
     void do_copy(T*& d, const T* s)
     {
       if(s) d=new(*s); else d=0; }};
     }
   };         

[UPDATE1] 詳細とその他の例:

そして、キューで deep_copy を使用します。

template <typename T>
class Queue {
public:
   void push_back(const T& elem)
   {
       Node* n = new Node();
       copyTraits.doCopy(n->elem, elem);
   }
private:
  deep_copy<T> copyTraits;
};

または、less<> がマップのデフォルトのように、テンプレートのデフォルト パラメータにすることをお勧めします。

template <typename T, typename CopyTraits = deep_copy<T> >
class Queue {
public:
   void push_back(const T& elem)
   {
       Node* n = new Node();
       copyTraits.doCopy(n->elem, elem);
   }
private:
  CopyTraits copyTraits;
};

Queue::~Qeueu()また、 d-tor を安全にしたい場合は、destroy メソッドを忘れないでください。

  template <typename T>
  struct deep_copy {
     void do_copy(T& d, const T& s)
     {
        d = s;
     }
     void do_destroy(const T& elem) {} // do nothing
  };


   template <typename T>  
   struct deep_copy<T*> {
     void do_copy(T*& d, const T* s)
     {
       if(s) d=new(*s); else d=0; }};
     }
     void do_destroy(const T& elem) {
       delete elem;
     }
   };         


template <typename T, typename AllocTraits = deep_copy<T> >
class Queue {
public:
   ...
   ~Queue() {
      for (n in Nodes) { // pseudo-code
         allocTraits.doDestroy(n->elem);
      }
   }
private:
  AllocTraits allocTraits;
};
于 2012-09-07T22:51:56.783 に答える
1

コードの重複が少し発生しますがQueue、ポインター型を使用したインスタンス化用にクラスを特殊化することができます。コードの重複の量を減らすための私の推奨事項は、各特殊化されたクラスが継承する基本クラスを作成することです。基本クラスには、クラスの型に応じて変更されないすべてのメソッドとメンバーが含まれます。でインスタンス化。

たとえば、次のようになります。

template<typename T>
base_queue; //keep everything "common" in this class

template<typename T>
queue : public base_queue<T> { ... }; //unspecialized queue class

template<typename T>
queue<T*> : public base_queue<T> { ... }; //pointer specialized version

Queue<T*>クラスの特殊化されたバージョンでは、enqueueメソッドは次のようになります。

template <typename T>
bool Queue<T*>::enqueue(const T* item)
{
    //... code

    add->item = *item; // copy the value being pointed to, not the pointer itself

    //... more code

    return true;
}
于 2012-09-07T21:55:57.457 に答える