C++ 模版类重载流输入输出运算符

在 C++ 中只能通过友元函数来重载流输入输出运算符 << >>。由于搭配模板类的使用,编译器可能在对应编译友元函数时无法确定其为模版,需要事先声明。

方法 1:提前声明并使用 <> 确认 #

#include <iostream>
using namespace std;

//需要提前进行声明,以使类中对友元函数的声明进一步确认函数为模板函数
template <class A> class complex;
template <class A> ostream & operator << (ostream &newout, const complex<A> &m);

template <class A>
class complex{ //以复数类为例
  private:
  	A real, image;
	public:
		complex(A a, A b):real(a),image(b){
		}

//在运算符 << 后加入 <> 以帮助编译器进一步确定该友元函数为模板函数
		friend ostream & operator << <>(ostream &newout, const complex<A> &m); 
}; 

template <class A>
ostream & operator << (ostream &newout, const complex<A> &m){
	newout<<"("<<m.real<<","<<m.image<<")";
	return newout;
}

int main(){
	complex<int> a(1,2);
	cout<<a<<endl;
	return 0;
} 

方法 2:在声明友元函数的同时定义友元函数 #

#include <iostream>
using namespace std;

template <class A>
class complex{
	private:
		A real, image;
	public:
		complex(A a, A b):real(a),image(b){
		}

//在声明友元函数的同时定义友元函数
		friend ostream & operator << (ostream &newout, const complex<A> &m){
			newout<<"("<<m.real<<","<<m.image<<")";
			return newout;
		}
}; 

int main(){
	complex<int> a(1,2);
	cout<<a<<endl;
	return 0;
} 

如果可以不使用友元函数 #

如果模板类中的成员为公有,则完全不需要在模板类中声明友元。

#include <iostream>
using namespace std;

template <class A>
class complex{
	public:
		A real, image; //成员为公有
		complex(A a, A b):real(a),image(b){
		}
//		friend ostream & operator << <>(ostream &newout, const complex<A> &m);
//友元在此是不必要的
}; 

template <class A>
ostream & operator << (ostream &newout, const complex<A> &m){
	newout<<"("<<m.real<<","<<m.image<<")";
	return newout;
}

int main(){
	complex<int> a(1,2);
	cout<<a<<endl;
	return 0;
} 

参考文章 #

Respond on Mastodon, webmention this post, or contact me directly.

You can use Hypothes.is to select texts and highlight.

You've copied this page url!

Search it in your Mastodon server, and reply that toot by @fanrongbin.com@fanrongbin.com.