c++基础语法 --模版

本文详细介绍了C++中的函数模板,包括其工作原理、使用方式(显式指定类型和类型推导)、重载、类模板以及常见容器(如vector、deque等)的构造和操作。实例演示了如何利用模板实现数组拼接、排序以及数据结构如pair和map的使用。
摘要由CSDN通过智能技术生成

模板

函数模板

  • 一个通用函数,函数类型和参数类型不具体指定
  • 函数模板把要处理的数据类型参数化,表现为参数的多态性
  • 模板关键字 template 类型关键字 typename
  • 函数模板使用的两种方式:
    1. 显示指定类型函数名 例:add(10, 20)
    1. 直接传值,靠类型推导 例: add(10, 0.1)
template<typename T,typename M>
M add(T t, M m) {
    return t + m;
}

template<typename T>
void tSwap(T& t1, T& t2) {
    T temp = t1;
    t1 = t2;
    t2 = temp;
}

int main(){
    int in1 = 10;
    double in2 = 20;
    cout<<in1<<","<<in2<<endl;
    double c = add(in1, in2);
    cout<<"in1 + in2 = "<<c<<endl;
    tSwap(c, in2);
    cout<<c<<","<<in2<<endl;
    return 0;
}
  1. 模板函数不会自动进行类型转换,普通函数会自动进行类型转换
  2. 如果同时匹配普通函数和模板函数,优先考虑普通函数
void fun(int n1, int n2) {
    cout<<"normal函数被调用"<<endl;
}
template<typename T>
void fun(T n1, T n2) {
    cout<<"template 函数被调用"<<endl;
}
int main() {
    fun(1, 'a');// 普通函数被调用
    fun(1, 1); // 普通函数被调用
    return 0;
}
函数模板的重载
class Person {
public:
    int age;
    Person(int age):age(age){}
};
template<typename T>
int compare(T n1, T n2) {
    if (n1 > n2) return 1;
    else if (n1 < n2) return -1;
    else return 0;
}
template<>
int compare<Person>(Person& p1, Person& p2) {
    if (p1.age < p2.age) return -1;
    else if (p1.age > p2.age) return 1;
    else return 0;
}

int main(){
    Person p1 = {19};
    Person p2 = {30};
    cout<< compare(p1, p2)<< endl;
    return 0;
}
练习
  1. 定义一个函数 将数组元素拼接为一个字符串 返回
#include<sstream>

using namespace std;
template<typename T>
string toString(T* arr, int len) {
    if (len == 0) return "[]";
    ostringstream oss;
    oss<<"[";
    for (int i = 0; i < len - 1; i++) {
        oss<<arr[i]<<",";
    }
    oss<<arr[len - 1]<<"]";
    return oss.str();
}

int main(){
    int arr[10];
    cout<<sizeof(arr)/ sizeof(int)<<endl;
    for (int i = 0; i < 10; i++) {
        arr[i] = i;
    }
    cout<<toString(arr, 10)<<endl;
    return 0;
}
  1. 定义一个函数模板 实现将一个数组中的元素升序排序返回
template<typename T>
void mySort(T* arr, int len) {
    for (int i = 0; i < len; i++) {
        for (int j = i + 1; j < len; j++) {
            if (arr[i] < arr[j]) continue;
            int t = arr[i];
            arr[i] = arr[j];
            arr[j] = t;
        }
    }
}

int main(){
    default_random_engine e;
    int arr[10];
    cout<<sizeof(arr)/ sizeof(int)<<endl;
    for (int i = 0; i < 10; i++) {
        arr[i] = e() * 1000 % 69;
    }
    for (int in : arr) cout<< in <<",";
    cout<<endl;
    mySort(arr, 10);
    for (int in : arr) cout<< in <<",";
    return 0;
}

类模板

  • 类模板不能自动类型转换,使用时必须声明使用类型
template<typename T>
class Numbercalculator {
private:
    T n1;
    T n2;
public:
    Numbercalculator(T n1, T n2): n1(n1), n2(n2){}

    void showAddResult() {
        cout<<n1 + n2 <<endl;
    }
};
int main(){
    Numbercalculator<int> numC = {1, 3};// 使用时必须声明类型
    numC.showAddResult();
    return 0;
}

vector容器的构造

// vector 的构造
    vector<int> v;
    vector<int> v1(10,1);// 容器里有10个1
    vector<int> v2 = v1;
    vector<int> v3(v2.begin(), v2.end());// 或 vector(v2.begin(), v2.begin() + 5)
    int arr[5] = {1,2,3, 4,1};
    vector<int> v4(arr, arr + 3);
vector的常用方法
size大小
capacity容量
使用swap对容器“瘦身”
vector<int>(v).swap(v);// 创建一个匿名对象,此时,匿名对象的容量大小都是原容器的元素个数,然后,再把原容器和匿名对象交换,原来的容器的容量和大小就变成大小了。

deque容器

和vector区别在于,vector是单向开口容器,deque是双向开口容器。vector内存不足时会重新开辟一块连续的空间,然后把原来的数据复制进去,deque是用引用分别指向不同空间,每个空间代表一个元素,如果要插入元素,只需要新增引用,在开辟一块空间。

stack

queue队列

list链表

set

  • 底层用二叉树实现,只能遍历不能修改。
  • 和multiset区别在于,不允许重复。
  • 不能用索引得到。
    |常用方法||
    |—|—|
    |lower_bound(int n)|返回第一个小于等于查找值的元素|
    |upper_bound(int n)|返回第一个大于等于查找值的元素|

pair

  • 两个数据的整合
    pair<string, int> p("小明", 18);
    cout<<p.first<<","<<p.second<<endl;
    pair<int, int> p = make_pair(12, 10);
    cout<<p.first<<","<<p.second<<endl;

map

    // 构造
    map<string, int> m;
    // 插入
    m.insert(pair<string, int>("小明", 18));
    m.insert(map<string, int>::value_type("history", 20));
    m.insert(make_pair("小红", 40));
    m["hhh"] = 666;
    // m.earse() 删除某个元素

    for (auto it = m.begin(); it != m.end(); it++) {
        cout<<(it->first)<<","<< (it->second)<<endl;
    }
    /*
        // 打印结果
        hhh,666
        history,20
        小红,40
        小明,18
    */
  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值