ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

关于C++模板类运算符重载在类内外实现的不同

2020-05-21 10:03:25  阅读:457  来源: 互联网

标签:return template C++ 运算符 ostream 编译器 istream operator 模板


最近在学习c++的模板,起初还挺顺利,但是在模板类遇到了一个IO流重载的问题

首先我是这样写的,但是不能编译

#include<iostream>
using namespace std;
template<typename T>
class A
{
    private:
        T c;
    public:
        A(){}
        friend ostream& operator<<(ostream& os, const A &a);
        friend istream& operator>>(istream& is, A &a);
};
istream & operator>>(istream& is, A& a) //问题出在这里 编译器提示我
{                                       //缺少 类模板 "A" 的参数列表 ostream 同理
    is >> a.c;
    return is;
}
ostream & operator<<(ostream& os, const A& a)
{
    os << "a: " << a.c << endl;
    return os;
}
int main()
{
    A<int> a;
    cin >> a;
    cout << a;
}

按照编译器的提示 我一步一步改成了这样

template<typename T>                              // 1
istream & operator>>(istream& is, A<T>& a)        //2
{
    is >> a.c;
    return is;
}
template<typename T>                            //3
ostream & operator<<(ostream& os, const A<T>& a)//4
{
    os << "a: " << a.c << endl;
    return os;
}

改了四处地方,编译器不给你看波浪线了,但是还是不能运行,编译运行编译器会给你这样报错

Undefined symbols for architecture x86_64:
“operator<<(std::__1::basic_ostream<char, std::__1::char_traits >&, A const&)”, referenced from:
_main in test-0193fd.o
“operator>>(std::__1::basic_istream<char, std::__1::char_traits >&, A&)”, referenced from:
_main in test-0193fd.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

**

但是,我把函数放在类内部实现

**

#include<iostream>
using namespace std;
template<typename T>
class A
{
    private:
        T c;
    public:
        A(){}
        friend ostream& operator<<(ostream& os, const A<T> &a)
        {
            os << "a: " << a.c << endl;
            return os;
        }
        friend istream& operator>>(istream& is, A<T> &a)
        {
            is >> a.c;
            return is;
        }
};
int main()
{
    A<int> a;
    cin >> a;
    cout << a;
}

然后我发现了一个BUG

#include<iostream>
using namespace std;
template<typename T>
class A
{
    private:
        T c;
    public:
        A(){}
        friend ostream& operator<<(ostream& os, const A &a) // 这里删掉了<T>
        {
            os << "a: " << a.c << endl;
            return os;
        }
        friend istream& operator>>(istream& is, A &a)  // 这里也是
        {
            is >> a.c;
            return is;
        }
};
int main()
{
    A<int> a;
    cin >> a;
    cout << a;
}

发现这样还是可以正常run,总是感觉不对劲,然后我去翻了一下《C++ Primer Plus》书上明确说明这样写是非法的,因为不存在A这样的对象必须要带上< T > 才合法。

最后说一下如何在类外实现IO流重载

找了好多篇博客发现都没有在类外实现IO流重载
有一篇博客解决了这个问题,作者的思路还是比较奇特,不过确实是解决了问题,给大家参考一下
网上搜到的一种解决方法
但是比较麻烦,我们可以有更简便的方法来实现


#include<iostream>
using namespace std;
template<typename T> class A;                           //前置声明
template <typename T> ostream & operator<<(ostream &os, const A<T> &a); 
template <typename T> istream & operator>>(istream &is, A<T> & a); 

template<typename T>
class A
{
    private:
        T c;
    public:
        A(){}
        friend istream& operator>> <T>(istream& is, A<T> &a);  
        // 这里要加一个<T>
        friend ostream& operator<< <T>(ostream& os, const A<T> &a); 
        //注意用空格将 <<与<T>隔开
};

template<typename T>                              
istream & operator>> (istream& is, A<T>& a)       
{
    is >> a.c;
    return is;
}
template<typename T>                            
ostream & operator<< (ostream& os, const A<T>& a)
{
    os << "a: " << a.c << endl;
    return os;
}

int main()
{
    A<int> a;
    cin >> a;
    cout << a;
}

这样就完美地在类外实现了IO流重载

所有代码都是在Mac下用vscode进行测试,但是经过我使用其他编译器,以及在Windows下测试所得结果一致,应该不会有太大差别。

标签:return,template,C++,运算符,ostream,编译器,istream,operator,模板
来源: https://blog.csdn.net/yezi_coder/article/details/106202044

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有