Что не так с этим шаблоном программы? - PullRequest
1 голос
/ 14 октября 2011

Я пытался изучать шаблоны в C ++, но меня немного смущает то, что я делаю неправильно.Мне сказали, как объявлять шаблоны друзей в FAQ о шаблонах, и я должен был сделать это с перегруженными операторами, но мне кажется, что мне трудно сказать, что у меня есть недопустимое количество аргументов (у меня должно быть 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;

}

Ответы [ 4 ]

2 голосов
/ 14 октября 2011

В дополнение к «Источники шаблона должны быть в заголовках», как указано в 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 голос
/ 14 октября 2011

Объявление:

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

Определение:

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

Они должны совпадать. Декларация одна права, кстати. Это также относится к оператору ostream

1 голос
/ 14 октября 2011

istream &Array<T>::operator>>( istream &input, Array &a ) не должно быть в классе Array<T>.

При этом он принимает неявный аргумент this, но вы явно передаете нужный массив в &a.

Измените эту строку (и соответствующую operator<<(эквивалентно) до istream &operator>>(istream &input, Array<T> &a) и он должен скомпилироваться.Это не повлияет на другие операторы istream из-за перегрузки функций.

1 голос
/ 14 октября 2011

Вы помещаете реализацию вашего шаблона в отдельный файл без явного создания экземпляров параметрируемых вами типов.

Другими словами, вам либо нужно явно создать экземпляр шаблона Array для типов, которые вы используете.используя или вам нужно сделать определение шаблона доступным с объявлением шаблона.То есть поместите все это в .cpp в шапку.

...