一:类模板的声明 要点都总结在程序中
#include <iostream>
using namespace std;
template <typename T>
class Complex
{
template <typename T1> //友元函数声明 注意:友元函数中的类型参数T1一定不要和类型参数T一样
friend ostream &operator<< (ostream &out, Complex<T1> &obj); //在类的内部声明模板类
//friend ostream &operator<< <T1> (ostream &out, Complex &obj); //这种写法是在类的外部定义
private:
T m_a;
T m_b;
public:
Complex();
Complex(T a, T b);
void show();
Complex operator+(Complex &obj);
/*friend ostream &operator<< (ostream &out, Complex &obj) //友元函数可以在类的内部实现
{
out << obj.m_a << "+" << obj.m_b << "i" << endl;
return out;
}*/
};
template <typename T>
Complex<T>::Complex()
{
m_a = 0;
m_b = 0;
}
template <typename T>
Complex<T>::Complex(T a, T b)
{
m_a = a;
m_b = b;
}
template <typename T>
void Complex<T>::show()
{
cout << m_a << "+" << m_b << "i" <<endl;
}
template <typename T>
Complex<T> Complex<T>::operator+(Complex<T> &obj) //返回值类型是类的对象,则对象类型不能省略 如第一个Complex<T>
{
Complex<T> tmp(m_a + obj.m_a, m_b + obj.m_b);
return tmp;
}
template <typename T> //类型参数与模板类的类型参数保持一致
ostream &operator<<(ostream &out, Complex<T> &obj)
{
out << obj.m_a << "+" << obj.m_b << "i" <<endl;
return out;
}
int main()
{
Complex<double> c1(1.1,2.2);
c1.show();
Complex<double> c2(3.4,5.6);
c2.show();
Complex<double> c3 = c1 + c2;
c3.show();
cout << c3 << endl;
return 0;
}
二:类模板的声明的拓展1(程序在一个文件中)
//类模板函数放在类的外部 注意:成员函数放在类的外部定义,需要将所有成员函数都设置为函数模板
#include <iostream>
using namespace std;
template <typename T> //先声明模板类
class Complex;
template <typename T> //声明模板类的友元函数
Complex<T> mysub(Complex<T> &a, Complex<T> &b);//因为不是类的内部函数,所以在定义对象时要显示的说明对象类型Complex<T>
//注意:声明时musub 后边不加<T>
template <typename T> //模板类
class Complex
{
template <typename T1>
friend ostream &operator<< (ostream &out, Complex<T1> &obj);
/*template <typename T2>
friend Complex<T2> mysub(Complex<T2> &a, Complex<T2> &b);*/ //友元函数第一种声明
friend Complex<T> mysub<T>(Complex<T> &a, Complex<T> &b); //友元函数第二种声明
private:
T m_a;
T m_b;
public:
Complex();
Complex(T a, T b);
void show();
Complex operator+(Complex &obj);
Complex operator-(Complex &obj);
};
template <typename T>
Complex<T>::Complex()
{
m_a = 0;
m_b = 0;
}
template <typename T>
Complex<T>::Complex(T a, T b)
{
m_a = a;
m_b = b;
}
template <typename T>
void Complex<T>::show()
{
cout << m_a << "+" << m_b << "i" << endl;
}
template <typename T>
Complex<T> Complex<T>::operator+(Complex<T> &obj) //返回值是类型是类的对象,则对象类型不能省略第一个Complex<T>
{
Complex<T> tmp(m_a + obj.m_a , m_b + obj.m_b);
return tmp;
}
template <typename T>
Complex<T> Complex<T>::operator-(Complex<T> &obj) //返回值是类型是类的对象,则对象类型不能省略第一个Complex<T>
{
Complex<T> tmp(m_a - obj.m_a , m_b - obj.m_b);
return tmp;
}
template <typename T>
ostream &operator<<(ostream &out , Complex<T> &obj)
{
out << obj.m_a << "+" << obj.m_b << "i";
return out;
}
template <typename T>
Complex<T> mysub(Complex<T> &a, Complex<T> &b) //函数声明必须和函数定义时的函数原型一致
{
Complex<T> tmp(a.m_a - b.m_a, a.m_b - b.m_b );
return tmp;
}
int main()
{
Complex<int> c1(1,2);
c1.show();
Complex<int> c2(3,4);
c2.show();
Complex<int> c3 = c1+c2;
c3.show();
Complex<int> c4 = c2-c1; //运算符-重载
c4.show();
cout << c4 << endl;
Complex<int> c5 = mysub(c2 , c1); //利用函数实现-
cout << c5 << endl;
return 0;
}
三:类模板的声明的拓展2(程序在不同的文件)
//complex.h文件
#ifndef COMPLEX_H
#define COMPLEX_H
#include <iostream>
using namespace std;
template <typename T> //先声明模板类
class Complex;
template <typename T> //声明模板类的友元函数
Complex<T> mysub(Complex<T> &a, Complex<T> &b);//因为不是类的内部函数,所以在定义对象时要显示的说明对象类型Complex<T>
//注意:声明时musub 后边不加<T>
template <typename T> //模板类
class Complex
{
template <typename T1>
friend ostream &operator<< (ostream &out, Complex<T1> &obj);
/*template <typename T2>
friend Complex<T2> mysub(Complex<T2> &a, Complex<T2> &b);*/ //友元函数第一种声明
friend Complex<T> mysub<T>(Complex<T> &a, Complex<T> &b); //友元函数第二种声明
private:
T m_a;
T m_b;
public:
Complex();
Complex(T a, T b);
void show();
Complex operator+(Complex &obj);
Complex operator-(Complex &obj);
};
#endif
#include "complex.h"
template <typename T>
Complex<T>::Complex()
{
m_a = 0;
m_b = 0;
}
template <typename T>
Complex<T>::Complex(T a, T b)
{
m_a = a;
m_b = b;
}
template <typename T>
void Complex<T>::show()
{
cout << m_a << "+" << m_b << "i" << endl;
}
template <typename T>
Complex<T> Complex<T>::operator+(Complex<T> &obj) //返回值是类型是类的对象,则对象类型不能省略第一个Complex<T>
{
Complex<T> tmp(m_a + obj.m_a , m_b + obj.m_b);
return tmp;
}
template <typename T>
Complex<T> Complex<T>::operator-(Complex<T> &obj) //返回值是类型是类的对象,则对象类型不能省略第一个Complex<T>
{
Complex<T> tmp(m_a - obj.m_a , m_b - obj.m_b);
return tmp;
}
template <typename T>
ostream &operator<<(ostream &out , Complex<T> &obj)
{
out << obj.m_a << "+" << obj.m_b << "i";
return out;
}
template <typename T>
Complex<T> mysub(Complex<T> &a, Complex<T> &b) //函数声明必须和函数定义时的函数原型一致
{
Complex<T> tmp(a.m_a - b.m_a, a.m_b - b.m_b );
return tmp;
}
//complex_main.cpp
//#include "complex.h" //这样写是错误的
#include "complex.cpp"
int main()
{
Complex<int> c1(1,2);
c1.show();
Complex<int> c2(3,4);
c2.show();
Complex<int> c3 = c1+c2;
c3.show();
Complex<int> c4 = c2-c1; //运算符-重载
c4.show();
cout << c4 << endl;
Complex<int> c5 = mysub(c2 , c1); //利用函数实现-
cout << c5 << endl;
return 0;
}
解释一下在主函数中出现的错误:
在这里我们不能像往常一样直接包含头文件(.h),而是要包含类模板的源文件(.cpp)。
(也可以直接把包含的源文件后缀名设置为.hpp而不是.cpp,表示头文件和源文件一起包含。 编译时直接 g++ xxx.cpp 即可 )