IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++-----------泛型模板(初级) -> 正文阅读

[C++知识库]C++-----------泛型模板(初级)

目录

1.泛型编程

2.函数模板?

2.1函数模板概念

?2.2函数模板实例化

2.21实例化分为两类:

2.22函数模板支持多个实例化参数?

2.3.模板参数的匹配问题?

2.31匹配原则

?3.类模板

3.1类模板格式与实例化

3.11格式:

4非类型模板参数


引言:C++为啥有模板类??

1:可用来创建动态增加或减少的数据结构

2:它与某种特定类型无关,因此代码可重复使用

3:它在编译时检查数据类型而不是运行时检查数据类型,保证了类型的安全

4:它是平台无关的,具有很好的移植性

1.泛型编程

引言:我们先来写一个交换函数

//交换int类型
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;
}

如果有字符型还需要来个char类型的重载,但是各位不觉得有些烦琐吗?而且调用的概率低的可怜,C++可是高级语言呢,那能不能改进一下呢?各位有没有见过模具,就比如做月饼等用的我们想让月饼啥样式就啥样式那种,C++也提供了一种解决方式---泛型编程

?模板是泛型编程的基础,使用反省编程可以编写与类型无关的通用代码,是代码复用的一种手段。

模板分为:

·类模板;

·函数模板

2.函数模板?

2.1函数模板概念

函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。

template<typename T1, typename T2,..., typename Tn >
返回值类型(一般是T)  函数名()
{
	//...
}

?template是模板参数,T是模板类型,typename是关键字一般可以用class代替但是不能用struct代替。

?就比如这个代码,intdouble都能编译,所以推出这个模板是有用的。

这就是高级语言的的高级之处,将我们应该重复做的自己给做了。?

其实这个Swap函数我们也不用写,C++库里已经写了

?我们直接用就行了。

?2.2函数模板实例化

2.21实例化分为两类:

隐式实例化显式实例化

隐式实例化就是让编译器根据实参推演模板参数的实际类型,如上述中的Swap函数。但是当我们传递的参数含有两种类型时,编译器无法推断T的具体类型,此时就需要我们使用显示实例化解决。

?解决方式1:我们手动将类型转换Add(a ,? (int)d );

解决方式2:显式实例化如下

显式实例化

??显示实例化:在函数名后面<>中指定参数类型。

? ? ? ? 如果类型不匹配,编译器会尝试进行隐式类型转换,如果无法转换成功编译器将会报错。

2.22函数模板支持多个实例化参数?

template<class K, class V> //两个模板参数
void Func(const K& key, const V& value)
{
?? ?cout << key << ":" << value << endl;
}
int main()
{
?? ?Func(1, 1); //K和V均int
?? ?Func(1, 1.1);//K是int,V是double
?? ?Func<int, char>(1, 'A'); //多个模板参数也可指定显示实例化不同类型
}

2.3.模板参数的匹配问题?

2.31匹配原则

1:一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数。

//专题函数
int Add(int left, int right)
{
	return left + right;
}
//模板函数
template<class T>
T Add(T left, T right)
{
	return left + right;
}
int main()
{
	Add(2, 3); 
}

各位猜猜编译器会调用那个add函数?

看反汇编得知用的是专题Add,

专题Add函数就是专门用来解决加法的,而模板函数只是一个备胎,让我们选反正我选专题函数。

2:对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板

 
 

?就比如这个代码,它与非模板函数不完全匹配并且调用模板函数的契合度更高,他就会调用模板函数。

3:模板函数不允许自动类型转换,但普通函数可以进行自动类型转换

?3.类模板

3.1类模板格式与实例化

引言:我们都知道typedef int SLDate ,那我们的实例化对象有int型又有double型呢,一个typedef就管不了这么多了所以来了个类模板

3.11格式:

?template<class T1, class T2, ..., class Tn>
class 类模板名
{
? ? // 类内成员定义
};

让我们用类模板写一个栈试试

//类模板完成栈
template<class T>
class Stack
{
public:
    Stack(size_t capacity = 0)
        :_a(nullptr)
        , _top(0)
        , _capacity(capacity)
    {
        if (capacity > 0)
        {
            _a = new T[capacity];
            _top = 0;
            _capacity = capacity;
        }
    }
    ~Stack();//类外定义

        void Push(const T& x)
    {
        if (_capacity == _top)
        {
            size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;
            T* tmp = new T[newcapacity];
            if (_a)
            {
                memcpy(tmp, _a, _top * sizeof(T));
                delete[] _a;
            }
            _a = tmp;
            _capacity = newcapacity;
        }
        _a[_top++] = x;
    }
    void Pop()
    {
        assert(_top > 0);
        _top--;
    }
    const T& Top()
    {
        assert(_top > 0);
        return _a[_top - 1];
    }
    bool Empty()
    {
        return _top == 0;
    }

private:
    T* _a;
    size_t _top;
    size_t _capacity;
};
//类外定义--加模板参数列表
template<class T>
Stack<T>::~Stack()
{
    delete[] _a;
    _top = _capacity = 0;
    _a = nullptr;
}

int main()
{
    Stack<int> s;//使用时需要显示提供参数类型
    s.Push(1);
    s.Push(2);
    s.Push(3);
    s.Push(4);
    s.Push(5);
    while (!s.Empty())
    {
        cout << s.Top() << " ";
        s.Pop();
    }
    cout << endl;
    return 0;
}

注意:类模板一定要指定,函数模板根据情况指定。如果模板函数不能推演就要指定指定模板参数进行显式实例化。

4非类型模板参数

它的名字有点绕,就是上面的类模板参数是泛型的根据需要能变成int,double,char等,但是这个非类模板参数就是这个参数当做一个常量来使用,比如我可以用它来指定一个数组的大小,数组大小就由我们随意改变即可。

template<class T,size_t N = 10>
class Mystack
{
public:
	//...
private:
	T _a[N];
	size_t _top;
};

int main()
{
	Mystack<int,100> st1; //100
	Mystack<int,200> st2; //200
	Mystack<int> st3; //可以给缺省参数:从右向左确,且连续
	return 0;
}

这个n就是非类模板参数。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-10-08 20:22:12  更:2022-10-08 20:25:29 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 4:47:47-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码