C++ 中的模板主要是函数模板和类模板 大致可以分为:模板函数 和模板类 其中模板类主要解决对象问题 。
第一部分:函数模板
1.在 C++ 中为了操作简洁我们引入了函数模板。所谓的函数模板实际上是建立一个通用函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来表达。这个通用函数就称为函数模板。凡是函数体相同的函数都可以用这个这个模板来取代模板中的虚拟类型,从而实现了不同函数的功能。
1).模板把函数或类要处理的数据类型参数化,表现为参数的多态性,成为类属。
2).模板用于表达逻辑结构相同,但具体数据元素类型不同的数据对象的通用行为。
这里简单举一个例子:
#include<iostream>
#include<algorithm>
using namespace std;
template <class T>
void swap1(T &a,T &b)
{
T t=a;
a=b;
b=t;
}
//void swap1(int &a, int &b)
//{
// int t = a;
// a = b;
// b = t;
//}
//void swap2(char &a, char &b)
//{
// char t = a;
// a = b;
// b = t;
//}
int main()
{
int x=2,y=4;
swap1<int>(x,y);
char a='a',b='b';
swap1(a,b);
cout<<x<<" "<<y<<endl;
cout<<a<<" "<<b<<endl;
system("pause");
return 0;
}
/*
4 2
b a
*/
template 关键字告诉编译器 ,我们要开始泛型了,不要随便报错。
我们可以看到函数模板的调用有两种形式: swap1<int> (a,b);
swap1(a,b);
2.来点稍微复杂一点的: 函数模板做函数参数:
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
template<class T,class T1>
void sortArray(T *a,T1 num)
{
T tmp;
int i,j;
for(i=0;i<num;i++)
{
for(j=i+1;j<num;j++)
{
if(a[i]<a[j])
{
tmp=a[i];
a[i]=a[j];
a[j]=tmp;
}
}
}
}
template<class T>
void Array1(T *a,int num)
{
int i=0;
for(i=0;i<num;i++)
{
cout<<a[i]<<" ";
}
}
int main()
{
int num=0;
// string a="agshjdbdsiiow"; //不能使用这个
// num=a.length();
char a[] = "ddadeeettttt";
num = strlen(a);
cout<<"排序之前\n";
Array1(a,num);
sortArray<char,int>(a,num);
cout<<"排序后\n";
Array1<char>(a,num);
system("pause");
return 0;
}
那么函数模板与普通函数有什么区别? 若两者同时出现,又会怎么样呢? 让我们一起来了解一下吧!!
区别:1)函数模板不允许自动类型转换,而普通函数能够进行自动类型转换。
如:char a='a'; 调用时使用变为 函数类型名 <int> (a); 这个时候如果直接进入函数模板就会报错,而进入普通函数就可以将 a 强制转换为 int 型。
调用规则: 1)函数模板可以像普通函数一样被重载
2)C++编译器优先考虑普通函数
3)如果函数模板可以产生一个更好的匹配,那么选择函数模板
4)可以通过空模板实参列表的语法限制编译器只通过模板匹配
#include<iostream>
#include<algorithm>
using namespace std;
int Max(int a,int b)
{
return a>b?a:b;
}
template <class T>
T Max(T a,T b)
{
return a>b?a:b;
}
template <class T>
T Max(T a,T b,T c)
{
return Max(Max(a,b),c);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int a=1,b=2;
// 当函数模板和普通函数都符合调用时,优先使用选择普通函数
cout<<Max(a,b)<<"\n"; //2
// 若显示使用函数模板,则使用 <> 类型列表
cout<<Max<>(a,b)<<"\n"; //2
// 如果函数模板产生更好的匹配使用函数模板
cout<<Max(3.0,4.0)<<"\n"; // 4
//重载
cout<<Max(5.0,6.0,7.0)<<"\n"; // 7 // 调用普通函数,可以隐式类型转换
cout<<Max('a',1)<<"\n"; // 97
system("pause");
return 0;
}
1)编译器并不是把函数模板处理成能够处理任意类的函数
2)编译器从函数模板通过具体类型产生不同的函数
3)编译器会对函数模板进行两次编译
在声明的地方对模板代码本身进行编译;在调用的地方对参数替换后的代码进行编译。
第二部分:类模板
类模板能干什么???
1)类模板用于实现类所需数据的类型参数化
2)类模板在表示如数据、表、图等数据结构显得特别重要
这些数据结构的表示和算法不受所含的元素类型的影响
template <类型形式参数表>
类声明
什么意思呢? 举个例子:
#include<iostream>
using namespace std;
template <typename T>
class A
{
public:
A(T t)
{
this->t=t;
}
T& getT()
{
return t;
}
protected:
public:
T t;
};
int main()
{
// 模板中如果使用了构造函数,则遵守以前的类的构造函数的调用规则
A<int> a(100);
a.getT();
return 0;
}
这是百度对这三种继承的解释:
1、public:public表明该数据成员、成员函数是对所有用户开放的,所有用户都可以直接进行调用
2、private:private表示私有,私有的意思就是除了class自己之外,任何人都不可以直接使用。
3、protected:protected对于子女、朋友来说,就是public的,可以自由使用,没有任何限制,而对于其他的外部class,protected就变成private。扩展资料:
三种类型的继承,父类的成员均被子类继承(之前的百科关于这点的描述是错误的),只是由类实例化的对象对其继承的成员的访问权限会有所变化。三种不同方式的继承,描述的是子类实例化对象对其成员的访问权限,并非是描述子类时,子类对继承自父类的成员的访问权限。
公有继承 继承自父类的成员保持不变。
私有继承 继承自父类的成员全部变为私有成员。
保护继承 继承自父类的公有成员变为保护成员,其余不变。