2014-05-13 168 views
1

我有一個模板類C.我想要這樣的模板拷貝構造函數,它將根據其他類的大小調整數據數組的大小。用模板拷貝構造函數替換默認拷貝構造函數

以下是一個簡單的例子。它工作正常。但是,請注意,Constructor 2Constructor 3如此相似,我想知道是否可以將它們合併爲一個?

另外,如果我簡單地刪除Constructor 3,那麼C<int> c3(c1)將不會調用Constructor 2,而是調用編譯器添加的默認拷貝構造函數。這將導致內存分配不當。

template<typename T> 
class C 
{ 
public: 
    T* val; 
    int size; 
public: 

    C(int s = 0) { 
     cout << "Constructor 1" << endl; 
     size = s; 
     val = (size) ? new T[size] : nullptr; 
    } 

    template<class T2> 
    C(const C<T2>& c2) { 
     cout << "Constructor 2" << endl; 
     size = c2.size; 
     val = (size) ? new T[size] : nullptr; 
    } 

    C(const C<T>& c2) { 
     cout << "Constructor 3" << endl; 
     size = c2.size; 
     val = (size) ? new T[size] : nullptr; 
    } 

    ~C() { 
     cout << "~C()" << endl; 
     delete[] val; 
     val = nullptr; 
    } 
}; 

int main(void) 
{ 
    C<int> c1(5); 
    C<float> c2(c1); 
    C<int> c3(c1); 

    return 0; 
} 

上述功能的輸出:

Constructor 1 
Constructor 2 
Constructor 3 
~C() 
~C() 
~C() 
+1

您可以在C++ 11中使用構造函數委託,也可以使用執行此初始化的成員函數(helper)。 – dyp

+0

假設你想對你正在分配的內存做一些有用的事情,構造函數2將使用來自源類型的對象做什麼? – Praetorian

+0

你打算在這些構造函數中執行'c2.val'元素的副本嗎? – dyp

回答

1

通過

template<class T2> 
C(const C<T2>& c2, int dummy) { 
    cout << "Constructor 2" << endl; 
    size = c2.size; 
    val = (size) ? new T[size] : nullptr; 
} 

template<class T2> 
C(const C<T2>& c2) : C(c2, 0) {} 

C(const C<T>& c2) : C(c2, 0) {} 

更新替換

template<class T2> 
C(const C<T2>& c2) { 
    cout << "Constructor 2" << endl; 
    size = c2.size; 
    val = (size) ? new T[size] : nullptr; 
} 

C(const C<T>& c2) { 
    cout << "Constructor 3" << endl; 
    size = c2.size; 
    val = (size) ? new T[size] : nullptr; 
} 

你可以使用:

C(int s = 0) { 
    cout << "Constructor 1" << endl; 
    size = s; 
    val = (size) ? new T[size] : nullptr; 
} 

template<class T2> 
C(const C<T2>& c2) : C(c2.size) {} 

C(const C<T>& c2) : C(c2.size) {} 

而不需要第二個構造函數。

+0

它不那麼優雅。但是,似乎這是擺脫這種情況的唯一方法。 –

+0

@YuchenZhong查看我的更新。 –

+0

通常,使用一種特殊的專用類作爲虛擬的類型和作出這樣的構造函數私有。這可以防止超載問題(類的用戶無意中調用該ctor)。 – dyp

0

一個想和一個C++ 11委派構造來實現此。然而,由於模板參數對於類或構造函數是不明確的,所以這不可能以直接的方式進行。作爲一種解決方法,可以將通用代碼分解爲輔助函數。

類似:

template<class T2> 
    C(const C<T2>& c2) { 
     Copy<T2>(c2); 
    } 

    C(const C<T>& c2) { 
     Copy<T>(c2); 
    } 

private: 
    template<class T2> 
    void Copy(const C<T2>& c2) { 
     cout << "Constructor 2" << endl; 
     size = c2.size; 
     val = (size) ? new T[size] : nullptr; 
    } 
+1

很確定第二個構造函數是委託給自己的。編輯:[是的,這是](http://coliru.stacked-crooked.com/a/c052b789d02eddef)。有趣的是,clang檢測到並拋出錯誤,而gcc segfaults。 – Praetorian

+0

@Praetorian:是的,你是對的。我正試圖讓大局出來。但是,沒有解決模板參數的問題。順便說一句,在VS你會得到「成功」的建設,除非你把警告視爲錯誤。我用一些不同的東西更新了答案,不會改變第二個ctor的簽名。 – Apriori