C++STL 模版技术

本文深入探讨了C++中的模板技术,包括函数模板和类模板。介绍了模板如何实现类型参数化,以及如何通过模板进行函数重载和类型推导。同时,讲解了模板函数与普通函数的调用规则,强调了模板函数不允许自动类型转换。此外,还讨论了类模板的使用,包括静态成员的处理。最后,文章提到了模板类的派生和分离式编译模式的应用。
摘要由CSDN通过智能技术生成

C++模版技术

  • 类型参数化,编写代码的时候可以忽略类型。

  • 为了让编译器区分普通函数和模版函数使用template关键字

  • template<class T>// 或者template<typename T>//告诉编译器,接下来写的函数是模版函数,避免报错。

void MySwap(T& a,T& b)//两数交换函数
{
int temp = a;
a = b;
b = temp;
}

模版函数能进行自动类型推导,会根据数据类型自动推导函数的数据类型。

void test()//自动类型推导
{
int a = 10; 
int b = 20;
MySwap(a,b);//编译器根据你传递过来的值,进行自动类型推导。
}

//显式的指定类型
MySwap<int>(a,b);

模版函数和普通函数的区别–函数模版不允许自动类型转换

函数模版和普通p函数一起调用的规则:

  1. 模版函数可以像普通函数那样被重载。

  2. C++编译器优先考虑普通函数。

  3. 如果模版函数可以产生一个更好的匹配,那么选择模版函数。

  4. 可以通过空模版实参列表的语法限定编译器只能通过模版匹配。

例:MyAdd<>(a,b );//强制使用模版函数。

函数模版机制结论:

  1. 编译器并不是把函数模板处理成任何类型的函数。

  2. 函数模板通过具体的类型产生不同的模版函数。

  3. 编译器会对函数模版进行两次编译,在声明的地方对函数模版本身进行编译,在调用的地方对参数替换后的代码进行编译。

类模版

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
template<class T>//不唯一
class Person {
public:
Person(T id, T age) {
this->mAge = age;
this->mID = id;
}
void Show()
{
cout << "ID" << mID << "Age" << mAge << endl;
}
public:
T mID;
T mAge;
};
void test01()
{
//函数模板在调用的时候,可以自动类型推导
//类模版必须显式制定类型
Person<int>p(10,20);
p.Show();
}
int main(void)
{
test01();
return 0;
}

模板类派生普通类

  • 模板类派生普通类时,必须要声明类型!
  • 模板类派生时,需要具体化模板类,因为C++编译器需要知道,父类的数据类型具体时什么样子的,才可以分配内存——即要知道父类所占内存大小是多少,只有数据类型固定下来,才知道如何分配内存。

示例:

template<class T>
class Person 
{
public:
Person()
{
mage = 0;
}
private:
T mage;
};
class sonPerson : public Person<int> //这里不加<int>,会生成失败
{ };

类模板派生模板类

模板类派生模板类时,可以不声明类型!

这样写就是正确的!为什么呢?

template<class T>
class Person 
{
public:
Person()
{
mage = 0;
}
private:
T mage;
};
template<class T>
class SonPerson2:public Person<T>
{
public:
SonPerson2() {};
SonPerson2() {};
private:
};

原因是在调用这个被派生的模板类时,我们需要先声明类型,所以此时编译器知道如何申请内存

分离式编译模式

Person.h(头文件中只写类的声明)
#pragma once//防止头文件重复包含
#include<iostream>
#include<string>
using namespace std;
class Person {
public:
Person(string name, int age);
void Show();
public:
string mName;
int mAge;
int mID;
};
//Person.cpp(写类的具体实现)
\#include"Person.h"
Person::Person(string name, int age)
{
this->mName = name;
this->mAge = age;
}
void Person::Show() {
cout << "Name" << " " << this->mName << " " << "Age" << " " << this->mAge << endl;
}
//main.cpp(类的实例化)
\#define _CRT_SECURE_NO_WARNINGS
\#include<iostream>
using namespace std;
\#include"Person.h"
int main(void)
{
Person p("AAA", 20);
p.Show();
return 0;
}

类模版在类内实现

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;
template<class T1,class T2>
class Person {
public:
Person(T1 name, T2 age) {
this->mName=name;
this->mAge = age;
}
void Show() {
cout << "Name" << this->mName << "Age" << this->mAge << endl;
}
public:
T1 mName;
T2 mAge;
};
void test01()
{
Person<string, int>p("AAA", 20);
p.Show();
}
int main(void)
{
test01();
return 0;
}

类模版遇到static成员

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
template<class T>
class Person{
public :
static int a;
};
//类外初始化
template<class T> int Person<T>::a = 0;
int main(void)
{
	Person<int> p1, p2, p3;
	Person<char>pp1, pp2, pp3;
	p1.a = 10;
	pp1.a = 100;
	cout << p1.a << " " << p2.a << " " << p3.a << endl;
	cout << pp1.a << " " << pp2.a << " " << pp3.a << endl;
	//若p1 p2 p3 和,pp1 pp2 pp3共享一个static成员的话,输出的这六个值应该相同
    // 每个生成的具体的类,共享自己的static成员
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值