禁止滥用友元函数,友元函数只用来进行左移<<、右移>>操作符重载
本质:模板是两次编译生成的,第一次生成的函数头和第二次生成的函数头不一样
情况一:类模板中所有函数的声明和实现写在类的内部
情况二:类模板中所有函数的声明与实现分离,写在同一.cpp中
以上两种情况相同,构造函数和普通函数正常声明和实现,只需要单独处理全局变量友元函数。
友元函数用来实现<<、>>操作符重载
friend ostream &operator<<<T>(ostream &out, Complex &c);
友元函数不是实现函数重载(非 << >>)
需要在类前增加类的前置声明函数的前置声明
template <typename T>
class Complex;
template <typename T>
Complex<T> MySub(Complex<T> &c1, Complex<T> &c2);
情况一:类模板中所有函数的声明和实现写在类的内部
#pragma warning(disable : 4996)
#include <iostream>
using namespace std;
template <typename T>
class Complex;
template <typename T>
Complex<T> MySub(Complex<T> &c1, Complex<T> &c2);
template<typename T>
class Complex
{
friend ostream &operator<<<T>(ostream &out, Complex &c);
//类的内部声明 必须写成
friend Complex MySub<T>(Complex &c1, Complex &c2);
public:
Complex(T _a, T _b)
{
this->a = _a;
this->b = _b;
}
void PrintComplex()
{
cout << "a:" << a << "b:" << b << endl;
}
Complex operator+(Complex &c)
{
Complex temp(this->a + c.a, this->b + c.b);
return temp;
}
Complex operator-(Complex &c)
{
Complex temp(this->a - c.a, this->b - c.b);
return temp;
}
private:
T a, b;
};
template<typename T>
ostream & operator<<(ostream & out, Complex<T> & c)
{
out << "a:" << c.a << "b:" << c.b << endl;
return out;
}
//友元函数实现 必须写成:
template<typename T>
Complex<T> MySub(Complex<T> &c1, Complex<T> &c2)
{
Complex<T> temp(c1.a - c2.a, c1.b - c2.b);
return temp;
}
int main()
{
Complex<int> c1(1, 2);
Complex<int> c2(3, 4);
Complex<int> c3 = c1 + c2;
cout << c3 << endl;
Complex<int> c4 = c1 - c2;
cout << c4 << endl;
//友元函数调用 必须写成
Complex<int> c5 = MySub<int>(c1, c2);
cout << c5 << endl;
system("pause");
return 0;
}
情况二:类模板中所有函数的声明与实现分离,写在同一.cpp中
#pragma warning(disable : 4996)
#include <iostream>
using namespace std;
template <typename T>
class Complex;
template <typename T>
Complex<T> MySub(Complex<T> &c1, Complex<T> &c2);
template <typename T>
class Complex
{
friend ostream &operator<<<T>(ostream &out, Complex &c);
friend Complex MySub<T>(Complex &c1, Complex &c2);
public:
Complex(T _a, T _b);
void PrintComplex();
Complex operator +(Complex &c);
Complex operator -(Complex &c);
private:
T a, b;
};
template <typename T>
Complex<T>::Complex(T _a, T _b)
{
this->a = _a;
this->b = _b;
}
template <typename T>
void Complex<T>::PrintComplex()
{
cout << "a:" << a << "b:" << b << endl;
}
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>::operator-(Complex<T> & c)
{
Complex temp(this->a - c.a, this->b - c.b);
return temp;
}
template <typename T>
ostream & operator<<(ostream & out, Complex<T> & c)
{
out << "a:" << c.a << "b:" << c.b << endl;
return out;
}
template <typename T>
Complex<T> MySub(Complex<T> &c1, Complex<T> &c2)
{
Complex<T> temp(c1.a - c2.a, c1.b - c2.b);
return temp;
}
int main1()
{
Complex<int> c1(1, 2);
Complex<int> c2(3, 4);
Complex<int> c3 = c1 + c2;
cout << c3 << endl;
Complex<int> c4 = c1 - c2;
cout << c4 << endl;
Complex<int> c5 = MySub<int>(c1, c2);
cout << c5 << endl;
system("pause");
return 0;
}
情况三:类模板中所有函数的声明与实现完全分离,包含.h、.cpp文件
注意在main.cpp中要包含 #include "Complex.cpp"
Complex.h
#pragma once
#pragma warning(disable : 4996)
#include <iostream>
using namespace std;
template <typename T>
class Complex;
template <typename T>
Complex<T> MySub(Complex<T> &c1, Complex<T> &c2);
template <typename T>
class Complex
{
friend ostream &operator<<<T>(ostream &out, Complex &c);
friend Complex MySub<T>(Complex &c1, Complex &c2);
public:
Complex(T _a, T _b);
void PrintComplex();
Complex operator +(Complex &c);
Complex operator -(Complex &c);
private:
T a, b;
};
Complex.cpp
#include "Complex.h"
template <typename T>
Complex<T>::Complex(T _a, T _b)
{
this->a = _a;
this->b = _b;
}
template <typename T>
void Complex<T>::PrintComplex()
{
cout << "a:" << a << "b:" << b << endl;
}
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>::operator-(Complex<T> & c)
{
Complex temp(this->a - c.a, this->b - c.b);
return temp;
}
template <typename T>
ostream & operator<<(ostream & out, Complex<T> & c)
{
out << "a:" << c.a << "b:" << c.b << endl;
return out;
}
template <typename T>
Complex<T> MySub(Complex<T> &c1, Complex<T> &c2)
{
Complex<T> temp(c1.a - c2.a, c1.b - c2.b);
return temp;
}
main.cpp
#pragma warning(disable : 4996)
#include <iostream>
#include "Complex.cpp"//重要
using namespace std;
int main()
{
Complex<int> c1(1, 2);
Complex<int> c2(3, 4);
Complex<int> c3 = c1 + c2;
cout << c3 << endl;
Complex<int> c4 = c1 - c2;
cout << c4 << endl;
Complex<int> c5 = MySub<int>(c1, c2);
cout << c5 << endl;
system("pause");
return 0;
}