《C++大学教程》学习笔记(十六)

《C++大学教程》学习笔记(十六)

本节并没有参考Deitel的书,而是参考了本科教材以及郑莉的书。

1.模版

1.1基本知识

若一个程序的功能是对任意类型的数据作同样的处理,则将所处理的数据类型说明为参数,就可以把这个程序改写为模版。模版提供了重用程序源代码的有效方法,方便了大规模的软件开发。

C++中的模版分为类模版(class template)和函数模版(function template)。

1.2函数模版

要注意区分函数模版模版函数

  • 函数模版就是数据类型参数(抽象)化的函数定义,是一个函数族,代表的是一类函数。
  • 当编译系统发现用指定数据类型调用函数模版时,就创建了一个模版函数,模版函数是一个实例化的具体函数。

关于函数模版的定义和使用,以及重载模版函数,下面给出一个实例:

#include <iostream>
#include <string>
using namespace std;

//定义一个函数模版
template <class T>
T Max(T a,T b){
    cout << "Template function called...\n";
    return (a > b ? a : b);
}

//定义第一个重载模版函数
string Max(string a,string b){
    cout << "string function called...\n";
    return (a.compare(b) > 0 ? a : b) ;
}

//定义第二个重载模版函数,一定要有const
const char * Max(const char* a,const char* b){
    cout << "const char* function called...\n";
    return (strcmp(a,b) > 0 ? a : b) ;
}

int main(){

    string str1 = "abcd";
    string str2 = {"abab"};

    cout << Max(123, 124) << endl;        //调用函数模版生成对应的模版函数
    cout << Max(3.134,3.135) << endl;     //调用函数模版生成对应的模版函数
    cout << Max(str1,str2) << endl;       //首选函数名、参数类型都匹配的函数
    cout << Max("abcd", "abab") << endl;  //C++认为这里的"abcd"的类型是const char*

    return 0;
}

运行结果如下图所示:
这里写图片描述

从上面这个实例可以看出,当编译器在处理重载模版函数的问题时,遵循的原则是:首选函数名、参数类型都匹配的具体函数,再找模版

另外我发现当输入的参数是“abcd”这种情况时,编译器会无视定义成string或者char*的重载函数,而是选择函数模版生成具体的模版函数。这是由于C++默认“abcd”这类输入的类型是const char*,因此我们得把函数的参数及返回类型都改成const char*。

1.3类模版

同样,要注意区分类模版模版类

  • 类模版是模版的定义,不是一个实实在在的类,定义用到通用类型参数。
  • 模版类是实实在在的类定义,是类模版的具体实例化。

同样给出一个类模版的实例:

#include <iostream>
#include <string>
using namespace std;

template <class T1,class T2>
class MyTemplateClass {
private:
    T1 x;
    T2 y;

public:
    MyTemplateClass(T1 xx,T2 yy)
    :x(xx),y(yy)
    {}

    void print(){
        cout << "x:" << x <<endl
        << "y:" << boolalpha << y << endl;
        //boolalpha代表以布尔值输出而不是0和1
    }
};

int main(){

    MyTemplateClass<double, string> mytc1(3.222,"hello");
    MyTemplateClass<int, bool> mytc2(64,false);

    mytc1.print();
    mytc2.print();

    return 0;
}

运行结果是:
这里写图片描述

这里的类模版用到了两种类型的参数,所以实例化时也要给出两个具体的类型。

2.STL(Standard Template Library)

2.1简介

C++提供的标准模版库(STL)是面向对象程序设计(OOP)与泛型程序设计(Generic Programming)思想相结合的一个良好典范。
STL为通用容器、迭代器、和建立在它们之上的算法提供模版。使程序设计者无需了解STL的基本原理,便可以使用其中的数据结构和算法。

构建STL框架最关键的四个组件是容器(container)、迭代器(iterator)、算法(algorithm)和函数对象(function object)。

其中,算法处于核心地位,迭代器如同算法和容器之间的桥梁

2.2容器

容器类是容纳、包含一组元素或元素集合的对象。
当容器类包含不同类型的元素时,称为异类容器类;当包含相同类型的元素时,称为同类容器类

容器类库包含7种基本的容器:

  • 向量(vector)
  • 双端队列(deque)
  • 列表(list)
  • 集合(set)
  • 多重集合(multiset)
  • 映射(map)
  • 多重映射(multimap)

这7种容器中,向量、双端队列和列表属于顺序容器(sequence container),而(多重)集合以及(多重)映射属于关联容器(associative container)。

2.3迭代器

迭代器是面向对象版的指针,它们提供了访问容器和序列中每个元素的方法。
迭代器有5种基本类别:

  • 输入
  • 输出
  • 前向
  • 双向
  • 随机

以及两种迭代器适配器:逆向迭代器适配器插入迭代器适配器

2.4适配器

适配器是一种接口类,为已有的类提供新的接口。
适配器可分为:

  • 容器适配器
  • 迭代器适配器
  • 函数对象适配器

2.5实例

下面给出一个综合了容器、迭代器、算法及函数对象的实例,代码如下所示:

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;

int main(){

    vector<int> v(5);
    ostream_iterator<int> output1(cout," "); //绑定标准输出装置,每个输出元素的分隔符为空格
    ostream_iterator<int> output2(cout,","); //绑定标准输出装置,每个输出元素的分隔符为逗号
    int n;

    cout << "Input 5 integers:\n";
    vector<int>::iterator pos = v.begin();   //使用迭代器
    while (pos != v.end()) {       
        cin >> n;
        *pos = n;        //与指针用法很相似
        pos++;
    }

    cout << "Vector v contains: ";
    copy(v.begin(), v.end(), output1);

    sort(v.begin(), v.end());        //从小到大排序,默认
    cout << "\nAfter sorted in ascending,Vector v contains: ";
    copy(v.begin(), v.end(), output1); //copy()会将存储在v中的每个元素一一写到由output所表示的ostream上头,每个元素皆以空格符分隔开来。

    sort(v.begin(), v.end(), greater<int>());   //从大到小排序,需要使用函数对象,greater的意思是大于
    cout << "\nAfter sorted in descending,Vector v contains: ";
    copy(v.begin(), v.end(), output2); //copy()会将存储在v中的每个元素一一写到由output所表示的ostream上头,每个元素皆以,分隔开来。

    cout << endl;
    return 0;
}

执行的结果如下图所示:
这里写图片描述
重要的信息都在注释里。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值