【问题标题】:What is wrong with this template program?这个模板程序有什么问题?
【发布时间】:2011-10-13 22:56:12
【问题描述】:

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

谢谢。

数组.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

数组.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;

}

【问题讨论】:

  • 请包括您的编译器的错误输出——您对它所说内容的描述含糊。
  • 您在哪一行出现错误?
  • Array.cpp:104: error: âstd::istream& Array::operator>>(std::istream&, Array&)â 必须只采用一个参数 Array.cpp :114: error: âstd::ostream& Array::operator&)â 必须只取一个参数
  • 您的 operatorthis 3 个)。
  • 尝试从这两个函数中删除Array&lt;T&gt;:: 限定符。

标签: c++ templates compiler-errors


【解决方案1】:

除了 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 个参数。

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 虽然这是正确的,但不这样做会导致链接器错误,并且听起来 OP 正在收到编译器错误。所以我认为这不能回答 OP 的直接问题。
    【解决方案3】:

    声明:

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

    定义:

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

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

    【讨论】:

      【解决方案4】:

      istream &amp;Array&lt;T&gt;::operator&gt;&gt;( istream &amp;input, Array &amp;a ) 不应属于 Array&lt;T&gt; 类。

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

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

      【讨论】:

      • istream 输入运算符使用非常量引用写入,因此不应为 const。
      • 正确的istream,但Array&lt;T&gt; 应该是const(打印不应该修改它正在打印的东西)。
      • cin &gt;&gt; array 应该修改数组。他的operator &lt;&lt; 有一个const Array&lt;T&gt;&amp;(用于打印),他的operator &gt;&gt;(用于输入)有一个Array&lt;T&gt;&amp;
      • 你完全正确。现在修复它! (不知何故我忘记了istream 读取,尽管你提醒。)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-25
      • 1970-01-01
      相关资源
      最近更新 更多