模板与泛型

返回总目录

  • 模板定义

  1.1 函数模板

#include<iostream>
using namespace std;
// 对字符数组,int排序
template <typename T, typename T1>
int mySort(T *arry, T1 size)
{
	int temp;
	if (arry == NULL)
		return -1;
	for (int i = 0; i < size;i++)
		for (int j = i + 1; j < size; j++)
		{
			if (arry[i] < arry[j])
			{
				temp = arry[i];
				arry[i] = arry[j];
				arry[j] = temp;
			}
		}
	return 0;
}
template <typename T, typename T1>
int myPrint(T *arry, T1 size)
{
	T1 i;
	for (i = 0; i < size; i++)
		cout << arry[i] << " ";
	return 0;
}
int main()
{
	{
		int myarry[] = { 11, 22, 10, 23, 20, 55 };
		int size = sizeof(myarry) / sizeof(*myarry);
		mySort<int, int>(myarry, size);//显示调用
		//mySort(myarry, size);

		printf("排序之后\n");

		myPrint(myarry, size);//自动推导出
		system("pause");
		return 0;
	}
	//char类型
	{
	char buf[] = "hdffsfefdf";
	int len = strlen(buf);
	mySort<char,int>(buf, len);
	myPrint<char,int>(buf, len);
	system("pause");
	return 0;
    }
}

  1.2 类模板

//complex.h
#include<iostream>
using namespace std;

template <typename T>
class Complex
{

  friend Complex Mysub(Complex &c1, Complex &c2);  //有元函数是全局函数,不属于这个类的

  friend ostream& operator<< <T>(ostream &out, Complex &c3);   //不加<T>报错LINK2019,两次编译每次生成的函数头不一样

public:
  Complex(T a, T b);
  void printCom();
  Complex operator+(Complex &c2);
  /*Complex operator-(Complex &c2);*/
protected:
private:
  T a;
  T b;
};
//complex.hpp

#include<iostream>
using namespace std;
#include "complex.h"
//构造函数写在类的外部..h和.cpp
template<typename T>
Complex<T>::Complex(T a, T b)
{
	this->a = a;
	this->b = b;
}
 template<typename T>
void Complex<T>::printCom() //函数的名前加类的域名,因为他是成员函数
{
	cout << "a:" << a << "b" << b << endl;
}
//成员函数,实现+运算符重载
template<typename T>
Complex<T> Complex<T>::operator+(Complex<T> &c2) //第一个是Complex<T>函数的返回值,参数也要具体化,名称也加域名;函数体内部要不要具体化无所谓
{
	Complex temp(a + c2.a, b + c2.b);
	return temp;
}
//成员函数,实现-运算符重载
//template<typename T>
//Complex<T> Complex<T>::operator-(Complex<T> &c2) //第一个是Complex<T>函数的返回值,参数也要具体化,名称也加域名;函数体内部要不要具体化无所谓
//{
//	Complex temp(c1.a - c2.a, c1.b - c2.b);
//	return temp;
//}
//友元函数实现<<重载
template<typename T>
ostream& operator<<(ostream &out, Complex<T>&c3) //全局函数,不属于类,不加域名
{
	out << "a:" << c3.a << " b:" << c3.b << endl;
	return out;

}
//友元函数实现-重载
template<typename T>
Complex<T> Mysub(Complex<T> &c1, Complex<T> &c2)  
{
	Complex temp(c1.a - c2.a, c1.b - c2.b);
	return temp;
}

函数实现放在体内

#include<iostream>
using namespace std;
template <typename T>
class Complex
{	

  friend Complex Mysub(Complex &c1, Complex &c2)
  {
  	Complex temp(c1.a - c2.a, c1.b - c2.b);
  	return temp;
  }
  //friend ostream& operator<<(ostream &out, Complex &c3);//函数体外实现
  friend ostream& operator<<(ostream &out, Complex &c3)
  {
  	out << "a:" << c3.a << " b:" << c3.b << endl;
  	return out;

  }
public:
  Complex(T a, T b )
  {	
  	this->a = a;
  	this->b = b;
  }
  //重载运算符
  Complex operator+(Complex &c2)
  {
  	Complex temp(a + c2.a, b + c2.b);
  	return temp;
  }
  void printCom()
  {
  	cout << "a:" << a << "b" << b << endl;
  }
protected:
private:
  T a;
  T b;
};
//ostream& operator<<(ostream &out, Complex &c3)
//{
//	out << "a:" << c3.a << " b:" << c3.b << endl;
//	return out;
//}
//测试代码
//#include "complex.h"
//#include "complex.cpp"//这里一点要注意了,要不然找不到函数体,两次编译惹的祸,所有常将cpp命名为hpp.与.h文件合二为一
#include "complex.hpp"
int main()
{   //需要将模板类具体化后,才能定义对象,C++编译器要分配内存
	Complex<int> c1(1, 2);
	Complex<int> c2(3, 4);
	Complex<int> c3 = c1 + c2;
	cout << c3 << endl;
	//滥用友元
	Complex <int> c4=Mysub(c1,c2);
	cout << c4 << endl;
	
	cout<<"hello..."<<endl;
	system("pause");
	return 0;
}

Example 2

//MyVector.h
#include<iostream>
using namespace std;
template<typename T>
class MyVector
{
	friend ostream & operator<< <T>(ostream &out, const MyVector &obj);
public:
	MyVector(int size = 0);
	MyVector(const MyVector &obj);//拷贝构造函数
	~MyVector();
public:
	T& operator[](int index);//中括号重载
	MyVector& operator=(const MyVector &obj);	
public:
	int getlen()
	{
		return m_len;
	}
protected:
private:
	T *m_space;
	int m_len;
};
//MyVector.cpp
#include<iostream>
using namespace std;
#include "MyVector.h"

template<typename T>
ostream & operator<<(ostream &out, const MyVector<T> &obj)
{	
	for (int i = 0; i < obj.m_len; i++)
	{
		out << obj.m_space[i]<<" ";
	}
	cout << endl;//换行
	return out;
}
//MyVector<int> myv1(10);构造函数
template<typename T>
MyVector<T>::MyVector(int size)
{
	m_space = new T[size];
	m_len = size;
}
//MyVector<int> myv2 = myv1;
template<typename T>
MyVector<T>::MyVector(const MyVector &obj)//拷贝构造函数根据myv1大小分配内存,cpy数据
{
	m_len = obj.m_len;
	m_space = obj.m_space;

	for (int i = 0; i < obj.m_len; i++)
	{
		m_space[i] = obj.m_space[i];
	}
}
template<typename T>
MyVector<T>::~MyVector()
{
	if (m_space != NULL)
	{
		delete[]m_space;
		m_space = NULL;//避免野指针
		m_len;
	}
}
template<typename T>
T& MyVector<T>::operator[](int index)//中括号重载
{
	return m_space[index];
}
//a3=a2=a1
template<typename T>
MyVector<T>& MyVector<T>::operator=(const MyVector<T> &obj)
{	
	//先把a2的旧的内存释放掉
	if (m_space != NULL)
	{
		delete[]m_space;
		m_space = NULL;//避免野指针
		m_len;
	}
	//根据a1分配内存
	m_len = obj.m_len;
	m_space = new T[m_len];
	//copy数据
	for (int i = 0; i < m_len;i++)
	{
		m_space[i] = obj.m_space[i];
	}
	return *this;//返回数组的引用,即a2;
}
//MyVector 测试代码
#include<iostream>
using namespace std;
#include "MyVector.cpp"
//#define _CRT_SECURE_NO_WARNINGS
class Teacher //1优化Teacher类,属性变成char *pname,构造函数里分配内存 2.析构函数释放pname指向的内存空间 3.避免浅拷贝,重载= ,重写拷贝函数 4,在teacher增加<<
{
public:  //在模板数组类,存int char,Teacher, Teacher*;
	Teacher()
	{
		age = 33;
		//strcpy(name, "");
		m_p = new char[1];
		strcpy(m_p, "");
	}
	
	Teacher(char *name, int age)
	{
		this->age = age;
		//strcpy(this->name, name);
		m_p = new char[strlen(name) + 1];
		strcpy(m_p, name);
	}
	Teacher(const Teacher &obj)
	{
		m_p = new char[strlen(obj.m_p) + 1];
		strcpy(m_p, obj.m_p);
		age = obj.age;
	}
	~Teacher()
	{
		if (m_p!=NULL)
		{
			delete[]m_p;
			m_p = NULL;
		}
	}
	void prinT()
	{
		//cout << name << "," << age << endl;
		cout << m_p << "," << age << endl;
	}
public:
	friend ostream & operator<<(ostream &out, Teacher &t);
	Teacher& operator=(const Teacher & obj)
	{
		if (m_p!=NULL)
		{
			delete[]m_p;
			m_p = NULL;
			age = 33;
		}
		m_p = new char[strlen(obj.m_p) + 1];
		age = obj.age;
		strcpy(m_p, obj.m_p);
		return *this;
	}
private:
	int age;
	//char name[32];
	char *m_p;    //深拷贝,和浅拷贝
};

ostream & operator<<(ostream &out, Teacher &t)
{
	out << t.m_p << "," << t.age << endl;
	return out;
}

void main()//存指针
{
	Teacher t1("Li", 30), t2("YU", 24), t3("Zhao", 21);
	MyVector<Teacher*>tArry(3);
	tArry[0] = &t1;  //t1丢进容器里面
	tArry[1] = &t2;
	tArry[2] = &t3;
	for (int i = 0; i < 3; i++)
	{
		Teacher *tmp = tArry[i];
		tmp->prinT();
	}
	//cout << tArry;//类对象没有实现左移,所以不能调用底层的<<重载
	system("pause");
}

void main7()
{
	MyVector<char> myv1(10);
	myv1[0] = 'a';
	myv1[1] = 'b';
	cout << myv1;
	system("pause");
}
int main6()
{	
	MyVector<int> myv1(10);
	for (int i = 0; i < myv1.getlen(); i++)
	{
		myv1[i] = i + 1;
		cout << myv1[i] << " ";
	}
	cout << endl;

	MyVector<int> myv2 = myv1;
	for (int i = 0; i < myv2.getlen(); i++)
	{
		cout << myv2[i] << " ";
	}
	cout << endl;
	cout << myv2 << endl;//重载操作符
	//operator<<(ostream &out,const MyVector &obj)
	cout << "hello..." << endl;
	system("pause");
	return 0;
}
  • 模板实参推断

  • 重载与模板

  • 可变参数模板

  • 模板特例化

                                                        回到顶部

发布了6 篇原创文章 · 获赞 4 · 访问量 540

猜你喜欢

转载自blog.csdn.net/Bigfish_k/article/details/104197139