这个模板程序有什么问题?

What is wrong with this template program?

本文关键字:什么 问题 程序      更新时间:2023-10-16

我一直在尝试学习c++模板,但我对我做错的事情有点困惑。我被告知如何在关于模板的FAQ上声明朋友模板,我不得不使用重载操作符这样做,但它似乎给我带来了麻烦,告诉我我在Array.cpp中有无效的参数(我应该有2个)。有什么办法能在保住我的操作员的同时解决这个问题吗。此外,简单的主文件是模板的正确语法吗?

谢谢。

Array.h:

#ifndef ARRAY_H
#define ARRAY_H
#include <stdexcept>
#include <iostream>
using namespace std;
template<typename T> class Array;
template<typename T> ostream &operator<<( ostream &, const Array<T> & );
template<typename T> istream &operator>>( istream &, Array<T> & );
template< typename T >
class Array
{

    friend ostream &operator<< <> ( ostream &, const Array<T> & );
    friend istream &operator>> <> ( istream &, Array<T> & );
 public:
    Array(  int = 10 ); 
    Array( const Array & ); 
    ~Array();
    int getSize() const; 
    const Array &operator=( const Array & ); 
    bool operator==( const Array & ) const; 

    bool operator!=( const Array &right ) const  
    { 
        return ! ( *this == right ); 
    }

    T &operator[]( T );              

    T operator[]( T ) const;  
 private:
    int size; 
    T *ptr;
};
#endif

Array.cpp

#include <iostream>
#include <iomanip>
#include <cstdlib> // exit function prototype
#include "Array.h" // Array class definition
using namespace std;
template< typename T >
Array<T>::Array( int arraySize )
{
    if ( arraySize > 0 )
        size = arraySize;
    else 
        throw invalid_argument( "Array size must be greater than 0" );
    ptr = new T[ size ]; 
    for ( int i = 0; i < size; ++i )
        ptr[ i ] = 0;
}
template< typename T >
Array<T>::Array( const Array &arrayToCopy ) 
   : size( arrayToCopy.size )
{
    ptr = new T[ size ];
    for ( int i = 0; i < size; ++i )
        ptr[ i ] = arrayToCopy.ptr[ i ];
}
template< typename T >
Array<T>::~Array()
{
    delete [] ptr; 
}
template< typename T >
int Array<T>::getSize() const
{
    return size;
}
template< typename T >
const Array<T> &Array<T>::operator=( const Array &right )
{
    if ( &right != this )
        {
            if ( size != right.size )
                {
                    delete [] ptr;
                    size = right.size; 
                    ptr = new T[ size ]; 
                }
            for ( int i = 0; i < size; ++i )
                ptr[ i ] = right.ptr[ i ]; 
        }
    return *this;
}
template< typename T >
bool Array<T>::operator==( const Array &right ) const
{
    if ( size != right.size )
        return false;
    for ( int i = 0; i < size; ++i )
        if ( ptr[ i ] != right.ptr[ i ] )
            return false; 
   return true; 
}
template< typename T >
T &Array<T>::operator[]( T subscript )
{
    if ( subscript < 0 || subscript >= size )
        throw out_of_range( "Subscript out of range" );
    return ptr[ subscript ];
}
template< typename T >
T Array<T>::operator[]( T subscript ) const
{
    if ( subscript < 0 || subscript >= size )
        throw out_of_range( "Subscript out of range" );
    return ptr[ subscript ]; 
}
// overloaded input operator for class Array;
// inputs values for entire Array
template< typename T >
istream &Array<T>::operator>>( istream &input, Array &a )
{
    for ( int i = 0; i < a.size; ++i )
        input >> a.ptr[ i ];
    return input; // enables cin >> x >> y;
} // end function 
// overloaded output operator for class Array
template< typename T> 
ostream &Array<T>::operator<<( ostream &output, const Array &a )
{
    int i;
    // output private ptr-based array 
    for ( i = 0; i < a.size; ++i )
        {
            output << setw( 12 ) << a.ptr[ i ];
            if ( ( i + 1 ) % 4 == 0 ) // 4 numbers per row of output
                output << endl;
        } // end for
    if ( i % 4 != 0 ) // end last line of output
        output << endl;
    return output; // enables cout << x << y;
} // end function operator<<

主文件:

#include <iostream>
#include "Array.h"
using namespace std;

int main()
{
    Array<int> integers1( 7 ); // seven-element Array
    Array<int> integers2; // 10-element Array by default

    // print integers1 size and contents
    cout << "Size of Array integers1 is "
         << integers1.getSize()
         << "nArray after initialization:n" << integers1;
}

除了MSN指出的'模板源应该在头中'之外,源文件中用于重载流操作符的行列如下:

template<typename T> istream &Array<T>::operator>>( istream &input, Array &a )
template<typename T>  ostream &Array<T>::operator<<( ostream &output, const Array &a ) 

然而,你想要完成的正确语法是头文件中使用的:

template<typename T> istream &operator>>( istream &input, Array<T> &a )
template<typename T> ostream &operator<<( ostream &output, const Array<T> &a ) 

头文件中的声明通常称为非成员流操作符。但是,源文件中的那些定义了一个成员移位操作符,它不能用于流,并且必须只有一个参数。

如果您更改声明以匹配头文件,则应该可以消除编译器问题。也就是说,您还需要将源文件的所有内容放入头文件或包含在第一个文件末尾的单独头文件中。如果您不这样做,当您尝试创建您的可执行文件时,您将得到链接器错误。

您将模板的实现放在一个单独的文件中,而没有显式地实例化您要参数化的类型。

换句话说,您要么需要显式地为您正在使用的类型实例化Array模板,要么需要通过模板声明使模板定义可用。也就是说,把。cpp文件中的所有内容放到header中。

声明:

template<typename T> istream &operator>>( istream &, Array<T> & );

定义:

istream &Array<T>::operator>>( istream &input, Array &a )
{

应该匹配。顺便说一句,声明一是对的。这也适用于ostream操作符

istream &Array<T>::operator>>( istream &input, Array &a )不应该在Array<T>类中。

就像这样,它需要一个隐式的this参数,但你显式地传递你想要的&a数组。

将该行(以及相应的operator<<)更改为istream &operator>>(istream &input, Array<T> &a),它应该可以编译。这不会因为函数重载而与其他istream操作符混淆。