C++模板

C++模板,第1张

C++模板

模板:把类型当做未知量

        不因类型的不同而需要重写代码。

int Max(int a, int b)
{
	return a > b ?  a:b;
}
char Max(char a, char b)
{
	return a > b ? a : b;
}

1 函数模板

        对于实现相同函数功能,因类型不同需要重写函数体而引入模板

        1.1. 模板声明

                template         //tyname可替换为class  _Ty 可以任意写

         1.2 单个多个未知类型

//引入模板,告诉编译器 下面的代码未知类型_Ty
// 单个未知类型
template
_Ty Max(_Ty a, _Ty b)
{
	return a > b ? a : b;
}
//多个未知类型 中间用逗号分隔
//下面两行可以写为一行//template void print(_Ty1 one, _Ty2 two, _Ty3 three)
template
void print(_Ty1 one, _Ty2 two, _Ty3 three)
{
	cout << one << two << three;
}
//返回值类型为 _Ty4
template
_Ty4 print(_Ty1 one, _Ty2 two, _Ty3 three)
{
	cout << one << two << three;
}

        1.3 函数模板调用

                隐式调用 :正常的函数传参即可调用

                显示调用:函数名<类型名>(参数)

                        显示调用所传参数类型必须与类型一致

template
_Ty Max(_Ty a, _Ty b)
{
	return a > b ? a : b;
}
template
void printTwo(_Ty1 a, _Ty2 b)
{
	cout<
void printSum(_Ty1 one,_Ty2 two)
{
	cout << one << " " << two << endl;
}

int main()
{
	//隐式调用
	cout << Max(1, 2) << endl;
	cout << Max("aaa", "nmmm") << endl;
	//显示调用 
	cout << Max("abf", "aaa") << endl; 
    cout<(1.1, 1.2)<("sss", 12);

//缺省情况 
	printSum("lalal",222);//隐式调用不明显
	printSum("wuwu",1111);	//显示调用 类型调用是可以缺省不写,但参数必须写

	return 0;
}

       

//存在传常量写法
//size_t: unsigned int 的别名
template 
void printArray(_Ty1 array)		//_Ty1=int *  ,size=3
{
	for (int i = 0; i < size; i++)
	{
		cout << array[i];
	}
	cout << endl;
}

void testFunc()
{
	
	int array[3] = { 1,2,3 };
	//没有做缺省必须显示调用
	printArray(array);
	//做了缺省可以隐式调用
	printArray(array);
	//不能传入变量,只能传入常量,函数模板如果存在变量的情况下
	//int size = 3;
	//printArray(array);
}
int main()
{
    testfunc();
    return 0;
}

        1.4 函数模板的两种形态

                1 普通函数当做函数模板

                        以上的例子全是普通函数当做函数模板

                2 类的成员函数是函数模板

class MM
{
public:
	template 
	void print(_Ty data)
	{
		cout << data << endl;
	}
	//去类外实现
	template void printdata(_Ty data);
protected:
};
template void MM::printdata(_Ty data)
{
	cout << data << endl;
}


int main()
{
	//类中的成员函数
	MM mm1;
	mm1.print(12);
	mm1.printdata(1234);
	mm1.printdata("hahhaha");

	return 0;
}

 2 类模板

        用template修饰的类就是类模板,用不用未知类型没关系

                必须采用显示调用

                类模板不是一个实际类型,所以所有用到类名的地方都需要使用类名<未知类型>方式使用

#include
using namespace std;
//没有这种写法
//template <>
//class MM
//{};

template 
class Lin
{
public:
	Lin() {}
	Lin(string name):name(name){}
	void print();
	void printSum();
protected:
	string name;
};
//类外实现 必须要加templat 
template 
void Lin<_Ty>::print()
{
	cout << "haha" << endl;
}
//继承
template 
class boy:public Lin<_Ty>
{
public:
	//子类的构造函数写法
	boy(string name) :Lin<_Ty>(name) {}

};

template 
class Data
{
public:
	Data(_Ty1 one, _Ty2 two) :one(one), two(two) {}
	void print();
protected:
	_Ty1 one;
	_Ty2 two;
};
template 
void Data<_Ty1, _Ty2>::print()
{
	cout << one << endl;
	cout << two << endl;
}


int main()
{
	//模板类的调用必须显示调用
	Lin gg;	//即使没有用到未知类型 也必须写出来
	Lin gg1;
	Lin gg2;
	//Lin gg;
	Lin gg3("xixi");
	gg3.print();

	Data mmInfo("小芳", 19);
	mmInfo.print();
	Data data(12, 11);
	data.print();

	return 0;
}

3 自定义类型当做模板参数

        基本自定义类型

        自定义类型也是一个模板

        模板传入自定义类型,关键在于运算符重载

#include
using namespace std;

class Car
{
public:
	Car(string num,double price) :num(num), price(price) {}
	friend ostream& operator<<(ostream& out, const Car& object)
	{
		out << object.num << " " << object.price << endl;
		return out;
	}
	bool operator>(Car& object)
	{
		return this->price > object.price;
	}
protected:
	string num;
	double price;
};

template 
void print(_Ty one)
{
	cout << one << endl;
}

template 
_Ty Max(_Ty one, _Ty two)
{
	return one > two ? one : two;
}

template 
class Node
{
public:
	Node(_Ty data, Node<_Ty>* next) :data(data), next(next) {}
	_Ty getData()
	{
		return data;
	}
	Node<_Ty>* getNext()
	{
		return next;
	}
protected:
	_Ty data;
	
	Node<_Ty>* next;		//至于为什是Node<_Ty>*  看前面类模板
	//正常写法 Node* next;
};


template 
class List
{
public:
	List()
	{
		headNode = nullptr;
	}

	void insertList(_Ty data)
	{
		headNode = new Node<_Ty>(data,headNode);
	}
	void printList()
	{
		Node<_Ty>* pmove = headNode;
		while (pmove != nullptr)
		{
			cout << pmove->getData() << endl;
			pmove = pmove->getNext();
		}
		cout << endl;
	}
protected:
	Node<_Ty>* headNode;
};

void testList()
{
	List list;
	list.insertList(1);
	list.insertList(2);
	list.insertList(3);
	list.printList();
	List carList;
	carList.insertList(Car("BYD",5000));
	carList.insertList(Car("LSLS", 50000));
	carList.insertList(Car("WL", 100));
	carList.printList();
}


int main()
{
	//基本数据类型做参数  隐式调用
	print(12);
	print("223");
	//基本数据类型做参数  显示调用
	print("12244");
	//自定义类型
	print(Car("dongfeng", 2000));
	Car DF("dongf",100000);
	Car BC("benchi",2000);

	Car result = Max(DF,BC);	//隐式调用
	//	Car result = Max(DF,BC);//显示调用 结果一致
	cout << result << endl;

	testList();

	return 0;
}

4 模板嵌套

明白类型是什么即可,适当可以借用using语法起别名 简化代码

#include
using namespace std;

template 
class Person
{
public:
	Person(_Ty1 name,_Ty2 age) :name(name), age(age) {}
	friend ostream& operator<<(ostream& out, const Person& p1)
	{
		out << p1.name << " " << p1.age << endl;
		return out;
	}
protected:
	_Ty1 name;
	_Ty2 age;
};

template 
class Car
{
public:
	Car(_Ty1 one, _Ty2 two) :one(one), two(two) {}
	void print()
	{
		cout << one << " " << two << endl;
	}
protected:
	_Ty1 one;
	_Ty2 two;

};
void testFunc()
{
	//类模板嵌套   类与类模板嵌套
	//Ty1 类型是 Person
	//Ty2 类型是 Person
	Car, Person>  car(Person("DZ",2222),Person(11,303));
	car.print();
	//上面两个等效下面四行
	

}


template 
void print(_Ty data)
{
	cout << data << endl;
}

int main()
{
	//隐式调用  普通函数与类模板嵌套
	print(Person("太一",232));
	//显示调用
	print>(Person("太一", 232));
	//看起来麻烦 起别名
	using PerType = Person;
	print(PerType("大古",12));

	testFunc();
	return 0;
}

5  模板函数的重载

#include 
using namespace std;

void print(int a, string b)
{
	cout << "普通函数" << endl;
}
template 
void print(_Ty1 a, _Ty2 b)
{
	cout << "两个类型" << endl;
}

template 
void print(_Ty a, _Ty b)
{
	cout << "一个类型" << endl;
}

int main()
{
	print(12, "显示调用百分调用模板");
	print(13,"字符串解析为char*类型,调用2个模板类型");
	print(12, string("优先调用适应的普通函数"));	//调用 普通函数
	//两个模板同时成立,优先调用类型相似度搞的那个
	print(12,12);//显示调用 强类型,会调用2个类型
	print(12, 12); // 隐式调用 解析成print需要做2次匹配 解析成 print做一次匹配  
					//优先调用匹配少的这种
	return 0;
}

6 模板特化

#include 
#include
#include 
using namespace std;
//两未知类型
template 
class MM
{
public:
	MM(_Ty1 one, _Ty2 two) :one(one), two(two) {}
	void print()
	{
		cout << one << " " << two << endl;
	}
protected:
	_Ty1 one;
	_Ty2 two;
};
class Data
{
public:
	Data(int a, int b) :a(a), b(b) {}
	void print()
	{
		cout << a << " " << b << endl;
	}
protected:
	int a;
	int b;
};

//局部特化,特殊化
template 
class MM<_Ty, _Ty>     //特化产生类,类名要用: 类名<类型> 方式使用
{
public:
	MM(_Ty one, _Ty two) :one(one), two(two) {}
	void print()
	{
		//cout << one << " " << two << endl; //要想输出需要重载,做特殊化不需要重载
		one.print();
		two.print();
		cout << "特殊化" << endl;
	}
protected:
	_Ty one;
	_Ty two;
};

//完全特化
//模板类没有位置类型,已经将类型具体化了  仍然是一个模板类

template <>
class MM
{
public:
	MM(string one, string two) :one(one), two(two) {}
	void print()
	{
		cout << "完全特化" << endl;
		cout << one << " " << two << endl;
	}
protected:
	string one;
	string two;
};

int main()
{
	//原生模板
	MM mm1("小芳", 18);
	mm1.print();

	//局部特化模板
	MM dMM(Data(1, 2), Data(3, 4));
	dMM.print();

	//完全特化的模板
	
	MM  mm2("小丽", "小美");
	mm2.print();

	tuple tp("张三", "李四");

	return 0;
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5659709.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存