簡體   English   中英

C++ 模板和鏈接器錯誤

[英]C++ Templates and a Linker Error

請考慮以下 C++ 程序:

#include <iostream>
using namespace std;

template <class T> class Array
{
    T *pType;
    int itsSize;
public:
    // template <class T>
    friend ostream &operator<< (ostream &, Array<T> & );
};

template <class T>
ostream &operator<<  (ostream &output, Array<T> &theArray)
  {
    return (output);
  }

ostream &operator<< (ostream &, Array<int> &);


int main ()
{
    Array<int> theArray;
    cout << theArray << endl;
    return 0;
}

上面的代碼可以編譯,但鏈接器給出了以下錯誤:

未定義符號 `operator<<(std::ostream&, Array&)'

我相信我需要告訴編譯器為運算符 << 實例化一個函數,但我不知道該怎么做。

鮑勃

不,您不需要告訴編譯器實例化模板,它會在需要時自行完成所有操作。

你的線路

ostream &operator<< (ostream &, Array<int> &);

實際上告訴編譯器你有一些其他Array<int>運算符,所以它不應該使用該類型的模板。

所以鏈接器去尋找另一個操作符,但當然沒有找到。

如果你只是刪除那個額外的聲明,它應該工作得更好。

聲明

ostream &operator<< (ostream &, Array<int> &);

不是告訴編譯器實例化模板。 它聲明了一個單獨且獨特的非模板化函數,即重載。

main()operator<<()的用法解析為聲明的函數。 編譯器不需要專門化模板來查找匹配項。 但是,由於沒有該函數的定義(即實現),鏈接失敗。

刪除該聲明,您應該會發現您的代碼可以編譯和鏈接。

順便說一句,輸出流操作符通常不會更改正在輸出的對象。 因此,建議將模板化的ostream &operator<< (ostream &, Array<T> & )更改為ostream &operator<< (ostream &, const Array<T> & )

此外,由於模板(通常)需要在頭文件中定義,並且頭文件包含在多個源文件中,因此最好避免using namespace std ,並將ostream替換為std::ostream

您的代碼存在問題,@BoPersson 和@Perter 指出了一些問題。
但是,即使您更改了他們的建議(這是 ideone 上的現場演示)並且我也在我的 VS 2015 上運行了它。 編譯器仍然很生氣。

Ideone 說:

prog.cpp:10:55: warning: friend declaration 'std::ostream& operator&)' declares a non-template function [-Wnon-template-friend]
     friend ostream &operator & );
                                                       ^
prog.cpp:10:55: note: (if this is not what you intended, make sure the function template has already been declared and add  after the function name here) 
/home/FHMhT9/ccNwcxP0.o: In function `main':
prog.cpp:(.text.startup+0x1b): undefined reference to `operator&)'
collect2: error: ld returned 1 exit status

VS 也給出了幾乎相同的錯誤。

Ideone 告訴我,類中的朋友聲明聲明了一個非模板函數。

因此,將類中的聲明更改為:

friend ostream &operator<< <T> (ostream &, Array<T> & );
//                        ^^^^^
// I added this <T> to tell the compiler that it is a template function.

但是需要在這之前定義函數,所以把operator<<的實現剪掉,然后貼在類之前。 但是你需要一個類的前向聲明才能工作。 所以最后你的代碼變得非常像這樣:

我也將Array<T> &更改為const Array<T> &

#include <iostream>

template <typename T>
class Array;

template <class T>
std::ostream &operator<<  (std::ostream &output, const Array<T> &theArray)
{
    output << "abc";
    return (output);
}

template <class T> class Array
{
    T *pType;
    int itsSize;
public:
    // template <class T>
    friend std::ostream &operator<< <T> (std::ostream &, const Array<T> &);
};

int main()
{
    Array<int> theArray;
    std::cout << theArray << std::endl;
    return 0;
}

這個版本現在可以使用了

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM