C++泛型编程(模板)

c++主要提供两种模板函数模板和类模板
注意:使用模板时必须确定出通用数据类型T,并且能够推导出一致类型
1,函数模板的作用:
建立一个通用函数,其函数返回值类型和参数类型可以不具体制定,用一个虚拟的类型来代表。
template:关键字template表明是声明模板。typename可以用class代替,cal名称可以替换叫做通用数据类型。

#include<iostream>
using namespace std;

template<typename cal>
void swap(int &a,int &b)
{
	int temp;
	temp = a;
	a = b;
	b = temp;
}

void swap(double& a, double& b)
{
	double temp;
	temp = a;
	a = b;
	b = temp;
}


int main()
{
	double a=20;
	double b = 10;
	
	//swap(a,b);//1,自动类型推导
	swap<double>(a, b);//2,显示指定类型
	char c='a';
    swap(a,c);//两个数据不一样错误
	cout << a <<"  "<< b << endl;

}

1.1普通函数与函数模板调用的差别
一般情况下我们写了函数模板就不会在写普通函数

#include<iostream>

using namespace std;

template<typename T>//模板函数必须与模板声明连着写否者会报错
T myadd(T a, T b)
{

	return a + b;
}

int myadd2(int a, int b)
{
	return a + b;
}




int main()
{
	int a = 10;
	int b = 20;
	char c = 'c';

	cout << myadd2(a, b) << endl;//普通函数调用
	cout << myadd2(a, c) << endl;//普通函数调用会出现自动隐式转换
	//cout<<myadd(a,b)<<endl;//自动类型推导模板函数不会发生自动类型隐式转换
	cout << myadd<int>(a, c) << endl;//显示指定类型模板函数不会发生自动类型隐式转换

	return 0;
}

1.2普通函数与函数模板调用规则
编译器调用规则如下:
1,如果函数模板和普通函数都可以实现,优先调用普通函数。
2,可以通过空模板强制调用
3,函数模板可以发生函数重载
4,如果函数可以产生更好的匹配,优先调用函数模板

#include<iostream>

using namespace std;

template<typename T>
T myadd(T a, T b)
{
	cout << "模板" << endl;
	return a + b;
}
template<typename T>
T myadd(T a, T b,T c)
{
	cout << "函数重载模板" << endl;
	return a + b;
}
int myadd(int a, int b)
{	
	cout << "函数" << endl;
	return a + b;
}




int main()
{
	int a = 10;
	int b = 20;
	int d = 20;
	char c = 'c';

	cout << myadd(a, b) << endl;
	cout << myadd(a, c) << endl;
	cout << myadd<>(a, b) << endl;//可以通过空模板强制调用
	cout << myadd<>(a, b,d) << endl;//函数重载模板

	return 0;
}

2.1类模板
类模板的作用:
建立一个通用类,类中的数据类型可以不具体制定,用一个假的类型来代替。
template
注意:类模板中成员函数和普通类中成员函数创建时机是有区别的:
普通类中的成员函数一开始就可以创建
类模板中的成员函数在调用时才可以创建

#include<iostream>
#include<string>
using namespace std;

template<class NAME,class AGE>
class person
{


public:
	person(NAME  name,AGE age)
	{
		this->m_Name = name;
		this->m_age = age;
	}
	void print()
	{
		cout<<this->m_age<<"  "<<this->m_Name << endl;
	}
public:
	NAME m_Name;
	AGE m_age;
};

int main()
{
	person<string, int>a("NB", 9999999);
	a.print();
	return 0;
}

2.2类模板与函数模板的区别
a,类模板使用只能用显示指定类型方式
b,类模板中的模板参数列表可以有默认参数
建议使用显示指定类型这样可以便于维护
c,调用类模板函数时才初始化,因为类模板是未知类型

#include<iostream>
#include<string>
using namespace std;

template<class NAME,class AGE=int>
class person
{


public:
        person(NAME  name,AGE age)
        {
                this->m_Name = name;
                this->m_age = age;
        }
        void print()
        {
                cout<<this->m_age<<"  "<<this->m_Name << endl;
        }
public:
        NAME m_Name;
        AGE m_age;
};

int main()
{
        person<string, int>a("NB", 9999999);//显示指定
        a.print();

        person<string>b("NB2",6666666);
        b.print();
        return 0;
}

2.3类模板对象做函数参数
a,指定传入类型–直接显示对象的数据类型(常用)
b,参数模块化—将对象中的参数变为模板进行传递
c,整个类模板化 – 将这个对象类型模板化进行传递

#include<iostream>
#include <typeinfo> 
#include<string>
#include <string> 
using namespace std;

template<class T1, class T2>
class person
{

public:
	void showperson()
	{
		cout << m_Name << ":" << m_Age << endl;
	}
	person(T1 name, T2 age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}
	T1 m_Name;
	T2 m_Age;

};

void print(person<string, int>& p)//指定传入类型--直接显示对象的数据类型
{
	p.showperson();

}
template<class T1, class T2>
void print1(person<T1, T2>& p)//参数模块化---将对象中的参数变为模板进行传递
{
	p.showperson();
	cout << "T1:" << typeid(T1).name() << endl;
	cout << "T2:" << typeid(T2).name() << endl;

}template<class T>
void print2(T &p)// 整个类模板化 -- 将这个对象类型模板化进行传递
{
	p.showperson();
	cout << typeid(T).name();

}
int main()
{
	person<string, int>p("NB", 6666);
	print2(p);
	return 0;
}

2.4模板类继承
如果父类是类模板,子类需要指定出父类中T的数据类型
如果不指定,编译器无法给子类分配内存
如果想灵活指定出父类中T的类型,子类也需变为类模板

#include<iostream>
using namespace std;


template<class T1>
class base
{
public:
	T1 a;


};
class son :public base<int>
{
public:
	void show()
	{
		cout << "nnnn" << endl;
	}


};
template<class T1, class T2>
class son2:public base<T2>
{
public:
	son2()
	{
		cout << typeid(T1).name() << endl;
		cout <<typeid(T2).name() << endl;
	}


};


int main()
{
	son2<int, char>p;

	return 0;
}

类模板,类外实现

#include<iostream>
using namespace std;


template<class Nametype,class Agetype>
class base
{
public:
	base(Nametype name,Agetype age);


	Nametype m_name;
	Agetype m_age;
};
template<class Nametype, class Agetype>//###########类模板,类外实现
base<Nametype,Agetype>::base(Nametype name, Agetype age)
{

	this->m_age = age;
	this->m_name = name;

}


int main()
{
	base<string, int> p("孙悟空",9999999);
	cout << p.m_name << p.m_age << endl;
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值