企业网站建设很有必要,怎样做月嫂网站,jsp做的网站代码,html 公司网站 代码下载个人主页#xff1a;平行线也会相交#x1f4aa; 欢迎 点赞#x1f44d; 收藏✨ 留言✉ 加关注#x1f493;本文由 平行线也会相交 原创 收录于专栏【C之路】#x1f48c; 本专栏旨在记录C的学习路线#xff0c;望对大家有所帮助#x1f647; 希望我们一起努力、成长平行线也会相交 欢迎 点赞 收藏✨ 留言✉ 加关注本文由 平行线也会相交 原创 收录于专栏【C之路】 本专栏旨在记录C的学习路线望对大家有所帮助 希望我们一起努力、成长共同进步。 目录 一、 泛型编程二、 函数模板2.1函数模板示例化2.2函数模板实例化的两种方式 三、类模板3.1类模板的实例化3.2类模板的声明和定义分离 一、 泛型编程
泛型编程好家伙名字倒是挺吓人其实并没有啥可怕的我们通过变换函数来引入泛型编程请看
void Swap(int left, int right)
{int temp left;left right;right temp;
}
void Swap(double left, double right)
{double temp left;left right;right temp;
}
void Swap(char left, char right)
{char temp left;left right;right temp;
}上述代码中我们可以对int类型、double类型、char类型进行交换在未来我们如果对更多类型的变量进行交换应该怎么呢 这个是问题刚好可以利用泛型参数来解决请看;
//模板
//函数模板类
templatetypename T
void Swap(T x1, T x2)
{T tmp x1;x1 x2;x2 tmp;
}
int main()
{int a 10, b 20;double c 1.1, d 2.2;Swap(a, b);Swap(c, d);return 0;
}模板参数定义的是函数的参数类型。 另外一点Swap(a, b);和Swap(c, d);调用的并不是同1个函数我们观察一下汇编代码来看一下 如果我们想要交换两个指针也是可以的请看int* p1 a;int* p2 b;swap如下图我们可以看到也可以交换指针 二、 函数模板
模板概念 函数模板代表了一个函数家族该函数模板与类型无关在使用时被参数化根据实参类型产生函数的特定类型版本。 2.1函数模板示例化
函数模板格式
//返回值类型 函数名(参数列表){}
templatetypename T
void Swap( T left, T right)
{T temp left;left right;right temp;
}上述代码是交换函数的一个代码那我们调用的时候并不是调用的那个模板编译器调用的其实是函数模板实例化生成的具体函数。 编译器通过模板生成具体函数的过程称之为函数模板的实例化。请看图 在编译器编译阶段对于模板函数的使用编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。比如当用double类型使用函数模板时编译器通过对实参类型的推演将T确定为double类型然后产生一份专门处理double类型的代码对于字符类型也是如此。 templatetypename T
void Swap(T x1, T x2)
{T tmp x1;x1 x2;x2 tmp;
}下面举多个参数类型的例子请看
templatetypename T1,typename T2
T1 Func(const T1 x, const T2 y)
{cout x y endl;return x;
}
//T1 T2可以是任意类型比如自定义类型或者内置类型
//函数模板实例化生成具体函数
//函数模板根据调用会自己推导模板参数的类型实例化出对应的函数
int main()
{Func(1, 2);Func(1.1, 2.2);return 0;
}注意templatetypename T1中的typename可以换成class但是不可以换成struct。
2.2函数模板实例化的两种方式
函数模板的实例化的两种方式分为隐式实例化和显式实例化。。 请注意看T Add(const T left, const T right)中为什么要加const这里涉及到权限的问题。举个例子cout Add(a1, (int)d1) endl;隐式类型转换 cout Adddouble(a1, d1) endl; 显式类型转换无论是显式类型的转换还是显式类型的转换类型的转换会产生临时变量临时变量具有常属性常属性不能传给普通的引用因为权限被放大了所以要加上const。 我能不能这样写呢请看 现在我们应该怎么解决呢首先这里解决方法有两种。 方式一两者之间只能听其中一个的话实参传递的时候推演T的类型 方式二显式实例化 上述的显式示例化其实并不是这样完的下面来看一下必须要用到显式示例化的场景。 三、类模板
3.1类模板的实例化
类模板的定义格式
templateclass T1, class T2, ..., class Tn
class 类模板名
{// 类内成员定义
}; 类模板实例化与函数模板实例化不同类模板实例化需要在类模板名字后跟然后将实例化的类型放在中即可类模板名字不是真正的类而实例化的结果才是真正的类。
templateclass T
class Stack
{
public:Stack(size_t capacity 10){/*_array (T*)malloc(capacity * sizeof(T));if (nullptr _array){perror(malloc申请空间失败);return;}*/_array new T[capacity];_size 0;_capacity capacity;}void Push(const T data){// CheckCapacity();_array[_size] data;_size;}~Stack(){if (_array){free(_array);_array nullptr;_capacity 0;_size 0;}}
private:T* _array;size_t _size;size_t _capacity;
};
int main()
{Stackint s1;//s1存int类型Stackdouble s2;//s2存double类型Stackchar s3;//s3存char类型return 0;
}3.2类模板的声明和定义分离
对于普通类而言类名就是类型。 对于类模板而言类名是类名类型是类型二者是不一样的。 请看下面举例
templateclass T
class Stack
{
public:Stack(size_t capacity 10);void Push(const T data);~Stack();
private:T* _array;size_t _size;size_t _capacity;
};templateclass T
StackT::Stack(size_t capacity)
{/*_array (T*)malloc(capacity * sizeof(T));if (nullptr _array){perror(malloc申请空间失败);return;}*/_array new T[capacity];_size 0;_capacity capacity;
}templateclass T
void StackT:: Push(const T data)
{// CheckCapacity();_array[_size] data;_size;
}templateclass T
StackT::~Stack()
{if (_array){free(_array);_array nullptr;_capacity 0;_size 0;}
}对于上述代码而言Stack是类名StackT是类型但是如果类模板实例化时候类名就是具体的Stackint或者Stackchar等。
关于类模板的声明和定义分离的讲解在模板进阶那一部分进行更深一步的讲解。
好了以上就是【C】模板初阶内容的讲解就到这里啦 再见啦友友们