鍍金池/ 問答/C++/ c++重載輸入輸出函數(shù)時(shí)怎么解決 “[Warning] declares a n

c++重載輸入輸出函數(shù)時(shí)怎么解決 “[Warning] declares a non-template function”?

我在做一道c++模板題,描述如下:
“為Array類創(chuàng)建一個(gè)模板。這個(gè)模板允許在編譯的時(shí)候Array對(duì)象實(shí)例化指定元素個(gè)數(shù)的特定的元素類型。”
而當(dāng)我重載輸入輸出流函數(shù)的時(shí)候編譯總是不通過。

編譯器顯示:
[Warning] friend declaration 'std::istream& operator>>(std::istream&, Array<T, n>&)' declares a non-template function [-Wnon-template-friend]
[Warning] friend declaration 'std::ostream& operator<<(std::ostream&, const Array<T, n>&)' declares a non-template function [-Wnon-template-friend]

代碼如下:

#include<iostream>
using namespace std;
template<class T,int n>
class Array
{
    private:
        T p[n];
        static int count;
    public:
        friend istream & operator>> (istream & in, Array<T,n>& a);
        friend ostream & operator << (ostream & out,const Array<T,n>& a);
        int getSize()
        {
            return n;
        }
        static int getArrayCount()
        {
            return count;
        }
};
template<class T,int n>
istream & operator >> (istream & in,const Array<T,n>& a)
{
    for(int i=0;i<n;i++)
    {
        in>>a.p[i];
    }
    a.count++;
    return in;
}
template<class T,int n>
ostream & operator << (ostream & out,const Array<T,n>& a)
{
    for(int i=0;i<n;i++)
    {
        out<<a.p[i]<<" ";
    }
    return out;
}

在此貼上主函數(shù):

int main()
{
    Array< int, 5 > intArray1;
    cin >> intArray1;
    Array< int, 5 > intArray2;
    cin >> intArray2;
    Array< float, 5 > floatArray;
    cin >> floatArray;
    cout << "\nIntArray1 contains " << intArray1.getSize() << " Elements.\n";
    cout << "The values in intArray are:\n";
    cout << intArray1;
    cout << "\nIntArray2 contains " << intArray2.getSize() << " Elements.\n";
    cout << "The values in intArray are:\n";
    cout << intArray2;
    cout << "\nDoubleArray contains " << floatArray.getSize() << " Elements.\n";
    cout << "The values in the doubleArray are:\n";
    cout << floatArray;
    cout << "\nThere are " << Array<int,5>::getArrayCount() << " Array<int,5> objects.\n";
    cout << "\nThere are " << Array<float,5>::getArrayCount() << " Array<float,5> objects.\n";
    return 0;
}

我在網(wǎng)上查了很久,也嘗試了很多解決方法,可是無(wú)論是在
istream & operator >> (istream & in,const Array<T,n>& a)
這一行里的 >> 后面加上 <> 還是把輸入輸出函數(shù)在類里面定義,都是不行。
如果在類里面定義的話,就會(huì)顯示如下錯(cuò)誤:
undefined reference to `Array<float, 5>::count'
[Error] ld returned 1 exit status

如果在 >> 后面加上 <> 的話,會(huì)顯示如下錯(cuò)誤:
[Error] template-id 'operator>><>' in declaration of primary template

所以現(xiàn)在舉步維艱,完全沒有頭緒。
還望各路大神能解答我的疑惑并解釋一下為什么會(huì)出現(xiàn)以上三種錯(cuò)誤。
萬(wàn)分感謝!

回答
編輯回答
扯不斷

@felix 老大已經(jīng)完全解答了OP你的問題, 窩稍微做點(diǎn)微不足道的補(bǔ)充:

  1. 將其聲明為類模板的友元會(huì)破壞類的封裝性, 比如X<int>的友元函數(shù)foo此時(shí)會(huì)對(duì)所有X<T>可見. 那么就等于X<int>間接不合理的獲取了所有X<T>的信息(比如其private member). 所以不建議使用, 比如下段代碼可以過編譯.
#include<iostream>
using namespace std;
template<typename T>
class A
{
private:
    T x;
    void setter(T y)
    {
        x = y;
    }
public:
    explicit A(T a) : x(a) {}
    template<typename U>
    friend void foo(A<U> a);
};
A<int> x(7);
template<typename U>
void foo(A<U> a)
{
    x.x = 2;
}
int main()
{
    A<int> a(7);
    A<float> b(1.1);
    foo(b);
}
  1. 還有第三種方式, 是使用前置聲明的方法, 詳見下面代碼.
  2. 首先靜態(tài)成員變量count需要在類外定義從c++1z開始可能需要改成首先non-constexpr的靜態(tài)成員變量count需要在類外定義。詳見http://eel.is/c++draft/depr.s... . demo可以在寫個(gè)odr-use函數(shù)試出.
  3. 題主你的const出問題了.
#include<iostream>
using namespace std;

template<class T, int n>
class Array;

template<class T, int n>
 istream & operator>> (istream & in, Array<T,n>& a);


template<class T,int n>
ostream & operator << (ostream & out,const Array<T,n>& a);

template<class T, int n>
class Array
{
private:
    T p[n];
    static int count;
public:
    friend istream & operator>> <> (istream & in, Array<T,n>& a);
    friend ostream & operator << <> (ostream & out,const Array<T,n>& a);
    int getSize()
    {
        return n;
    }
    static int getArrayCount()
    {
        return count;
    }
};
template<class T,int n>
istream & operator >> (istream & in, Array<T,n>& a)
{
    for(int i=0;i<n;i++)
    {
        in>>a.p[i];
    }
    a.count++;
    return in;
}
template<class T,int n>
ostream & operator << (ostream & out,const Array<T,n>& a)
{
    for(int i=0;i<n;i++)
    {
        out<<a.p[i]<<" ";
    }
    return out;
}

template<class T, int n>
int Array<T, n>::count = 0;


int main()
{
    Array< int, 5 > intArray1;
    cin >> intArray1;
    Array< int, 5 > intArray2;
    cin >> intArray2;
    Array< float, 5 > floatArray;
    cin >> floatArray;
    cout << "\nIntArray1 contains " << intArray1.getSize() << " Elements.\n";
    cout << "The values in intArray are:\n";
    cout << intArray1;
    cout << "\nIntArray2 contains " << intArray2.getSize() << " Elements.\n";
    cout << "The values in intArray are:\n";
    cout << intArray2;
    cout << "\nDoubleArray contains " << floatArray.getSize() << " Elements.\n";
    cout << "The values in the doubleArray are:\n";
    cout << floatArray;
    cout << "\nThere are " << Array<int,5>::getArrayCount() << " Array<int,5> objects.\n";
    cout << "\nThere are " << Array<float,5>::getArrayCount() << " Array<float,5> objects.\n";
    return 0;
}
2017年4月6日 02:11
編輯回答
陪她鬧

首先靜態(tài)成員變量count需要在類外定義。

其次,問題主要出在試圖將函數(shù)模板的某個(gè)特化聲明為類的友元,標(biāo)準(zhǔn)貌似不支持這個(gè)(具體的wording沒有找到)。同樣的效果可以通過簡(jiǎn)單的在類模板內(nèi)定義函數(shù)友元來(lái)實(shí)現(xiàn):

template <class T>
class X {
  friend void foo(T) { /* ... */ }
};

或?qū)⒑瘮?shù)模板聲明為類模板的友元:

template <class T>
class X {
  template <class U>
  friend void foo(U);
};
2017年8月25日 05:37