关于C++类模板内部 / 外部声明友元模板函数的那些事儿
1.内部声明定义友元类模板函数
例:
using namespace std;
template <typename T>
class Complex
{
friend ostream& operator<<(ostream& out, Complex& c)
{
out << c.a << "," << c.b ;
return out;
}
public:
Complex(T a, T b) :a(a),b(b){}
Complex operator+(Complex& c)
{
Complex temp(this->a + c.a, this->b + c.b);
return temp;
}
private:
T a;
T b;
};
int main()
{
Complex<int> a(1,2);
Complex<int> b(3, 4);
Complex<int> c = a + b;
cout << c << endl;
return 0;
}
运行结果:
2.内部声明,外部定义友元类模板函数
例:
using namespace std;
template <typename T>
class Complex {
friend ostream& operator<<(ostream& out, Complex<T>& c);
public:
Complex(T a, T b);
Complex<T> operator+(Complex<T>& c);
private:
T a;
T b;
};
template <typename T>
ostream& operator<<(ostream& out, Complex<T>& c)
{
out <<"(" << c.a << " , " << c.b << ")";
return out;
}
template <typename T>
Complex<T>::Complex(T a, T b)
{
this->a = a;
this->b = b;
}
template <typename T>
Complex<T> Complex<T>::operator+(Complex<T>& c)
{
Complex temp(this->a + c.a, this->b + c.b);
return temp;
}
int main()
{
Complex<int> c1(1, 2);
Complex<int> c2(3, 4);
Complex<int> c = c1 + c2;
cout << c << endl;
return 0;
}
运行结果:
别看啦大兄弟,这里出错也就是意料之中的事情,原因可以看下面:
这就是典型的 二次编译 的错误信息,找不到友元函数的函数实现。所以,如果友元模板函数的定义写在函数的外部,需要进行类和函数的前置声明,来让编译器找到函数的实现。
解决方法很简单,前置声明将能完美解决:
运行结果:
3.声明在.h文件,定义在.cpp文件
例:
using namespace std;
#include "demo.hpp"
int main()
{
Complex<int> c1(1, 2);
Complex<int> c2(3, 4);
Complex<int> c = c1 + c2;
cout << c << endl;
return 0;
}
using namespace std;
template <typename T>
class Complex;
template <typename T>
ostream& operator<<(ostream& out, Complex<T>& c);
template <typename T>
class Complex {
friend ostream& operator<< <T> (ostream& out, Complex<T>& c);
public:
Complex(T a, T b);
Complex<T> operator+(Complex<T>& c);
Complex<T> myAdd(Complex<T>& c1, Complex<T>& c2);
private:
T a;
T b;
};
template <typename T>
ostream& operator<<(ostream& out, Complex<T>& c)
{
out <<"("<< c.a << " , " << c.b << ")";
return out;
}
template <typename T>
Complex<T>::Complex(T a, T b)
{
this->a = a;
this->b = b;
}
template <typename T>
Complex<T> Complex<T>::operator+(Complex<T>& c)
{
Complex temp(this->a + c.a, this->b + c.b);
return temp;
}
template <typename T>
Complex<T> Complex<T>::myAdd(Complex<T>& c1, Complex<T>& c2)
{
Complex temp(c1.a + c2.a, c1.b + c2.b);
return temp;
}
这就是类模板的应用过程。