禁止濫用友元函數,友元函數只用來進行左移<<、右移>>操作符重載
本質:模板是兩次編譯生成的,第一次生成的函數頭和第二次生成的函數頭不一樣
情況一:類模板中所有函數的聲明和實現寫在類的內部
情況二:類模板中所有函數的聲明與實現分離,寫在同一.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;
}