lijialijialijia 发表于 2019-7-5 23:10:00

请教大神关于类模板和重载运算符的问题

我首先重载了一个加号运算符 程序运行起来没问题 但是按同样的方法重载一个输出运算符就报错 这是为什么??#include<iostream>
#include<string>

//在类定义的前面声明模板函数
template<classT>
voidShow_A( T & a);

template<class T>
Toperator+( T &a1 , T &a2);

template<class T>                                                                           //声明这条语句后 就报错
std::ostream & operator<<(std::ostream & os , const T & a1);


template<classT>
classA
{
private:
    Tmy_x;
    Tmy_y;
public:

    A(T x=0 , T y=0)    :   my_x(x) , my_y(y)       {std::cout<<"**********构造函数**********\n"; }
    ~A()                                          {std::cout<<"**********析构函数**********\n"; }

    A(const A & a);                                  //复制构造
    A & operator=(const A & a);                      //重载赋值运算符

//在类里面再次声明友元函数其参数是类模板类型
    friend void Show_A< A<T> >( A<T> & a );

    friendA<T>operator+< A<T> >( A<T> & a1 , A<T> & a2);

    friendstd::ostream & operator<<< A<T> >(std::ostream & os , A<T> &a1);




};


int main()
{
    A<double>a1(11.5 , 15.5);

    Show_A(a1);





    return 0;
}

template<class T>
std::ostream & operator<<(std::ostream & os , T a1)
{
    os<<"( "<<a1.my_x<<" , "<<a1.my_y<<"! )\n";

    return os;
}

template<class T>
Toperator+( T &a1 , T &a2)
{
    T temp;

    temp.my_x = a1.my_x+a2.my_x;
    temp.my_y = a1.my_y+a2.my_y;

    return temp;
}

//定义函数模板
template<classT>
void Show_A(T & a)
{
    std::cout<<"( "<<a.my_x<<" , "<<a.my_y<<"! )\n";

}


template<class T>
A<T> & A<T>::operator=(const A & a)
{
    my_x = a.my_x;
    my_y = a.my_y;

    std::cout<<"**********重载赋值运算符**********\n";
    return *this;
}

template<class T>
A<T>::A(const A & a)            //复制构造
{
    my_x = a.my_x;
    my_y = a.my_y;

    std::cout<<"**********复制构造函数**********\n";
}


请大神帮忙看看

Croper 发表于 2019-7-5 23:57:30

首先,“<<”和“>>”本质上是位运算符,
其之所以能作为流输出输入运算符,是因为在istream和ostream中对其已经进行了重载:template<class _Elem,
        class _Traits> inline
        basic_istream<_Elem, _Traits>& operator>>(
                basic_istream<_Elem, _Traits>& _Istr, _Elem *_Str)
        {        // extract NTBS
        typedef basic_istream<_Elem, _Traits> _Myis;
        typedef ctype<_Elem> _Ctype;
        ios_base::iostate _State = ios_base::goodbit;
        _Elem *_Str0 = _Str;
        const typename _Myis::sentry _Ok(_Istr);

        if (_Ok)
                {        // state okay, extract characters
                const _Ctype& _Ctype_fac = _STD use_facet<_Ctype>(_Istr.getloc());

                _TRY_IO_BEGIN
                streamsize _Count = 0 < _Istr.width() ? _Istr.width()
                        : (numeric_limits<streamsize>::max)();
                typename _Myis::int_type _Meta = _Istr.rdbuf()->sgetc();
                _Elem _Ch;
                for (; 0 < --_Count; _Meta = _Istr.rdbuf()->snextc())
                        if (_Traits::eq_int_type(_Traits::eof(), _Meta))
                                {        // end of file, quit
                                _State |= ios_base::eofbit;
                                break;
                                }
                        else if (_Ctype_fac.is(_Ctype::space,
                                _Ch = _Traits::to_char_type(_Meta))
                                        || _Ch == _Elem())
                                break;        // whitespace or nul, quit
                        else
                                *_Str++ = _Traits::to_char_type(_Meta);        // add it to string
                _CATCH_IO_(_Istr)
                }

        *_Str = _Elem();        // add terminating null character
        _Istr.width(0);
        _Istr.setstate(_Str == _Str0 ? _State | ios_base::failbit : _State);
        return (_Istr);
        }

template<class _Traits> inline
        basic_ostream<char, _Traits>& operator<<(
                basic_ostream<char, _Traits>& _Ostr,
                const char *_Val)
        {        // insert NTBS into char stream
        typedef char _Elem;
        typedef basic_ostream<_Elem, _Traits> _Myos;
        ios_base::iostate _State = ios_base::goodbit;
        streamsize _Count = (streamsize)_Traits::length(_Val);        // may overflow
        streamsize _Pad = _Ostr.width() <= 0 || _Ostr.width() <= _Count
                ? 0 : _Ostr.width() - _Count;
        const typename _Myos::sentry _Ok(_Ostr);

        if (!_Ok)
                _State |= ios_base::badbit;
        else
                {        // state okay, insert
                _TRY_IO_BEGIN
                if ((_Ostr.flags() & ios_base::adjustfield) != ios_base::left)
                        for (; 0 < _Pad; --_Pad)        // pad on left
                                if (_Traits::eq_int_type(_Traits::eof(),
                                        _Ostr.rdbuf()->sputc(_Ostr.fill())))
                                        {        // insertion failed, quit
                                        _State |= ios_base::badbit;
                                        break;
                                        }

                if (_State == ios_base::goodbit
                        && _Ostr.rdbuf()->sputn(_Val, _Count) != _Count)
                        _State |= ios_base::badbit;

                if (_State == ios_base::goodbit)
                        for (; 0 < _Pad; --_Pad)        // pad on right
                                if (_Traits::eq_int_type(_Traits::eof(),
                                        _Ostr.rdbuf()->sputc(_Ostr.fill())))
                                        {        // insertion failed, quit
                                        _State |= ios_base::badbit;
                                        break;
                                        }
                _Ostr.width(0);
                _CATCH_IO_(_Ostr)
                }

        _Ostr.setstate(_State);
        return (_Ostr);
        }
而你用不同的方式再次重载了这个符号,对于同一个运算,编译器能够找到不止一个能匹配的重载函数,就会出现定义不明确的错误
页: [1]
查看完整版本: 请教大神关于类模板和重载运算符的问题