2016-06-07 78 views
8

我寫了模板拷貝構造函數代碼,以獲得更好的理解這個概念,因爲我是新來的,但下面的代碼編譯失敗C++模板拷貝構造函數不可用或明確

#include <iostream> 
#include <vector> 

using namespace std; 

template <typename T> 
class Grid 
{ 
public: 
    explicit Grid(size_t inWidth = kDefaultWidth, size_t inHeight = kDefaultHeight); 
    virtual ~Grid(); 

    template <typename E> 
    Grid(const Grid<T>& src); 

    static const size_t kDefaultWidth = 10; 
    static const size_t kDefaultHeight = 10; 
    std::vector<std::vector<T>> mCells; 
    size_t mWidth, mHeight; 
}; 

template <typename T> 
template <typename E> 
Grid<T>::Grid(const Grid<T>& src) 
{ 
    cout << "Copy constructor working " << endl; 

} 

int main() 
{ 
    Grid<double> myDoubleGrid; 
    Grid<double> newDoubleGrid(myDoubleGrid); 
    return 0; 
} 

在編譯上面以下錯誤Visual Studio代碼出現: -

錯誤: -

Severity Code Description Project File Line Suppression State Error C2558 class 'Grid': no copy constructor available or copy constructor is declared 'explicit'

我試圖爲E來代替參數的模板,它顯示了更多的錯誤(奇怪的)

template <typename T> 
template <typename E> 
Grid<T>::Grid(const Grid<E>& src) 
{ 
    cout << "Copy constructor working " << endl; 

} 

錯誤:

Severity Code Description Project File Line Suppression State Error LNK2019 unresolved external symbol "public: __thiscall Grid::Grid(unsigned int,unsigned int)" ([email protected]@@[email protected]@Z) referenced in function _main

Error LNK1120 2 unresolved externals

Error LNK2019 unresolved external symbol "public: virtual __thiscall Grid::~Grid(void)" ([email protected]@@[email protected]) referenced in function "public: virtual void * __thiscall Grid::`scalar deleting destructor'(unsigned int)" ([email protected]@@[email protected])

+2

是的,我只是在公衆後面:訪問說明符 –

+4

'Grid :: Grid(const Grid &src)'...'T'和'T',E有什麼用? –

+0

它可能會在稍後使用,我打算將其用於其他目的,儘管它是可以忽略的 –

回答

9

模板構造函數永遠不會(!)複製構造函數。代碼中的構造函數只是一個轉換構造函數。

你可能想都:

#include <iostream> 
#include <vector> 

// Please do not have this ugliness in a header! 
using namespace std; 

template <typename T> 
class Grid 
{ 
public: 
    explicit Grid(size_t inWidth = kDefaultWidth, size_t inHeight = kDefaultHeight) 
    // initialize members ... 
    {} 

    // Without this copy-constructor the compiler generates a copy-constructor 
    // (with no output, of course) 
    Grid(const Grid& src) 
    // initialize members ... 
    { 
     cout << "Copy constructor" << endl; 
    } 

    template <typename E> 
    Grid(const Grid<E>& src) 
    // initialize members ... 
    { 
     cout << "Converting constructor" << endl; 
    } 

    static const size_t kDefaultWidth = 10; 
    static const size_t kDefaultHeight = 10; 
    size_t mWidth, mHeight; 
}; 

int main() 
{ 
    Grid<double> myDoubleGrid; 
    Grid<double> newDoubleGrid(myDoubleGrid); // Copy constructor 
    Grid<int> newIntGrid(myDoubleGrid);  // Converting constructor 
    return 0; 
} 

參見:

+0

好吧,我明白了問題謝謝! –

+0

順便說一句如果我用Grid(const Grid &src)替換Grid(const Grid &src),它不給出錯誤,但是如何訪問這個版本? –

+0

的'模板網(常量電網 & src);'是'模板網(常量電網& src);'是沒用的。 –

1

注意Grid<T>(Grid<U> const&)在技術上不是一個拷貝構造函數,它是一個轉換構造函數。編譯器仍然爲你生成一個拷貝構造函數。

+0

但編譯器不生成任何默認的複製構造函數,這就是爲什麼錯誤出現 –

1

到您撥打的大事情由於你的愚蠢錯誤,正在發生令人尷尬的錯誤: -

1)您已經爲構造函數和析構函數提供了聲明。正如你所說,它是你唯一的源文件。這意味着你一定沒有定義它們,哪個是你得到的鏈接器錯誤的原因。有時候這些非常簡單的問題可能被證明是非常危險和耗時的。

如果您不想提供任何詳細的實現,您可以用一對大括號替換分號。

2)您正在嘗試執行的操作完全沒有邏輯性,因爲您正在創建一個類似於複製構造函數的ssignature的轉換器構造函數。無論如何,編譯器會優先考慮複製構造函數而不是轉換器構造函數。

最終,您的構造函數定義永遠不會被調用。

+0

感謝您的建議 –