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

时间:2011-10-13 22:56:12

标签: c++ templates compiler-errors

我一直在尝试用C ++学习模板,但是我对我做错了什么感到困惑。我被告知如何在关于模板的常见问题解答中声明朋友模板,我必须使用重载的运算符来执行此操作,但它似乎让我很难告诉我在我的数组中有无效的参数(我应该有2个)。 CPP。有什么办法可以解决这个问题,同时保留我的操作员。另外,简单的主文件是模板的正确语法吗?

谢谢。

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;

}

4 个答案:

答案 0 :(得分:2)

除了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 ) 

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

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

答案 1 :(得分:1)

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

换句话说,您需要为正在使用的类型显式实例化Array模板,或者需要使用模板声明使模板定义可用。即,将.cpp中的所有内容放入标题中。

答案 2 :(得分:1)

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

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

将该行(以及相应的operator<<等效地)更改为istream &operator>>(istream &input, Array<T> &a),它应该编译。由于函数重载,这不会与其他istream运算符混淆。

答案 3 :(得分:1)

声明:

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

定义:

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

这些应该匹配。声明一个是对的,顺便说一下。这也适用于ostream运算符