C++学习摘要7

第17章 模板与类型转换

  • 模板的定义及目的
    将一种数据类型定义为参数,然后将不同数据类型按照实参形式传送而实现代码重用(类似与java的泛型机制),减少由于类型不同而产生的无所谓的重载。
  • 模板的定义及使用
#include<iostream>
using std::cout;
using std::endl; 
template<class T>
T min(T x,T y){
    return (x<y)?x:y;
} 
int main(){
    int n1 = 2,n2 = 10;
    double d1 = 1.5,d2 = 5.6;
    //隐式调用
    cout<<"较小的整数"<<min(n1,n2)<<endl;
    //显示调用
    cout<<"较小的实数"<<min<double>(d1,d2)<<endl;
    return 0;
}
  • 模版的特殊化,模板中有一个具体实现
#include<iostream>
using namespace std;
template<class T>
class Pair{
    T value1,value2;
    public :
        Pair(T first,T second){
            value1 = first;
            value2 = second;
        }
        T module(){
            return 0;
        }
};


template<>
class Pair<int>{
    int value1,value2;
    public:
        Pair(int first,int second){
            value1 = first;
            value2 = second;
        }
        int module(){
            return value1%value2;
        }
};
int main(){
    Pair<int> myints(100,75);
    Pair<float>myfloats(100.0,75.0);
    cout<<myints.module()<<endl;
    cout<<myfloats.module()<<endl; 
    return 0;
}
  • 重载和函数模版
    函数模板重载的参数匹配规则如下:
    1.寻找和使用最符合函数名和参数类型的涵数。
    2.寻找一个函数模版,将其实例化产生一个匹配的函数。
    3.寻找可以通过类型转换的参数匹配的重载函数。
    4.如果未找到则调用错误,如果找到的多于一个匹配则出现二义性。

  • 运行时类型识别
    在C++中类型识别是指只有一个指向基类的指针或引用时,确定一个对象的准确类型。派生类的特殊性可以通过定义虚函数加以体现,运行时类型检查只有在必要时才使用(影响效率).

    两种使用方法:1.运行时识别类型typeid

    shape *sh1 = new circle;
    cout<<typeid(*sh1).name()<<endl;
 2.运行时类型强制转换dynamic_cast
#include<iostream>
#include<typeinfo>
using namespace std;
class shape{
    int s1;
    int s2;
    int s3;
    public:
    virtual void draw(); 
};

void shape::draw(){
    cout<<"shape drawing "<<endl;
}

class circle:public shape{
    int t1;
    int t2;
    int t3;
    public :
        void draw();
};
void circle::draw(){
    cout<<"circle drawing"<<endl;
}

int main(){

    shape *sh1 = new circle;
    cout<<typeid(*sh1).name()<<endl;
    sh1->draw();

    circle *cp = dynamic_cast<circle *>(sh1);
    if(cp){
        cout<<"case sucessful"<<endl;
        cp->draw();
    }


    return 0;
}

强制类型转换运算符

1.static_cast
最常用的类型转换符,在正常状况下的类型转换,如把int转换为float,如:

int i;float f; f=(float)i;
或者f=static_cast<float>(i);

2.const_cast
用于取出const属性,把const类型的指针变为非const类型的指针,如:

const int *fun(int x,int y){}  int *ptr=const_cast<int *>(fun(2.3))

3.dynamic_cast
该操作符用于运行时检查该转换是否类型安全,但只在多态类型时合法,即该类至少具有一个虚拟方法。dynamic_cast与static_cast具有相同的基本语法,dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。如:

class C

{
  //…C没有虚拟函数
};
class T{
  //…
}
int main()
{
  dynamic_cast<T*> (new C);//错误
}
此时如改为以下则是合法的:
class C

{
public:
  virtual void m() {};// C现在是 多态
}

4.reinterpret_cast
interpret是解释的意思,reinterpret即为重新解释,此标识符的意思即为数据的二进制形式重新解释,但是不改变其值。如:

int i; char *ptr="hello freind!"; i=reinterpret_cast<int>(ptr);这个转换方式很少使用。

第18章 容器和迭代器

  • 迭代器的概念及意义
    迭代器是一种检查容器内的元素并遍历元素的数据类型。
  • 常用的迭代器
    1.输入迭代器
    必须能读取其所指向的值,支持的操作有*p,++p,p++,p!=q,p==q,凡是支持这五类操作的类都可以称为输入迭代器,*p只允许读取,不许修改。

    2.输出迭代器
    必须能对指向的序列进行写操作,支持的操作同上五种
    但是*p所返回的值允许修改,而不一定要读取。

    3.前向迭代器
    支持的操作相同,但*p既可以读取也可以修改。

    4.双向迭代器
    进一步支持操作符自减如p–,–p.

    5.随机存取迭代器
    允许随机访问序列的任意值,如指针。

    迭代器类型可以使用解引用操作符(*)来访问,如*iter = 0;

  • C++中的容器有顺序容器和关联容器
    顺序容器
    将单一容器聚集起来成为容器,然后根据位置来存储和访问数据
  • 1.向量vector类似与java中的arraylist
    主要操作有:
    v.push_back();//在数组的最后一个添加一个值
    v.size();//数组大小
    v.empty();//判空
    v[n];//返回v中位置为n的元素
    v1=v2;把v1的元素替换成v2的副本
    v1==v2;判断是否相等
    vector进行初始化时如果没有指定元素初始化,则标准库自行提供一个初始化值进行初始化。

  • 2.双端队列
    元素可以从队列的两端出队和入队,支持使用[]访问,必须引入头文件deque
    主要操作有:
    d.push_back(3);//从后插入
    d.push_front(10);//从前插入
    d.insert(1,88);//在一号位置插入,原来1号及后面的数据往后移,
    d.begin();//起始位置
    deque不提供容量操作,capacity(),reverse();

  • 3.列表
    列表主要用于存放双向链表,可以从任意一端开始遍历,列表还提供了拼接操作,将一个序列中的元素插入到另一个序列中,需要引入头文件list
    主要操作有:
    l.push_back();
    l.push_front();
    l.erase();//删除

#include<iostream>
#include<list>
using namespace std;
int main(){

    //定义list 
    list<int>elemets;
    //定义迭代器
    list<int>::iterator iter;

    //向list中当前的指针位置插入,直到最后一位
    elemets.push_back(8);
    elemets.push_back(5);
    //在当前的位置插入,直到最前一位 
    elemets.push_front(2);

    //进行迭代遍历
    for(iter = elemets.begin();iter != elemets.end();iter++){
        cout<<"元素:"<<*iter<<endl;
    }

    cout<<"删除元素首位后"<<endl;

    //删除list首位
    elemets.erase(elemets.begin());
    //进行迭代遍历
    for(iter = elemets.begin();iter!=elemets.end();iter++){
        cout<<"元素:"<<*iter<<endl;
    } 
    return 0;
}
  • 关联容器

通过键值存取数据的集合。关联容器的读取和存储和数据写入的顺序无关,只根据键值来指定对应的元素。

  • 1.集合和多集
    一个集合是一个容器,所包含的元素是唯一的(set)。集合的元素按一定的顺序排列(平衡二叉树),并被作为集合中的实例。通过链表实现。如果要修改集或多级容器中的元素值,必须先删除原有的元素,在插入新元素。
    集合和多集的区别:
    集(set)支持唯一键,集中的值都是特定的,并且只出现一次。而多集(multiset)中可以出现副本键,一个值可以出现多次。
#include<iostream>
#include<set>
using namespace std;
int main(){
    set<int>set1;
    for(int i=0;i<10;i++){
        set1.insert(i);
    }
    for(set<int>::iterator p=set1.begin();p!=set1.end();++p){
        cout<<*p<<""; 
    }
    cout<<endl;
    if(set1.insert(3).second){
        cout<<"插入成功"<<endl;
    }else{
        cout<<"插入失败"<<endl;
    }

    int a[] = {4,1,1,1,1,0,5,1,0};
    multiset<int> A;
    A.insert(set1.begin(),set1.end());
    A.insert(a,a+9);
    cout<<endl;

    for(multiset<int>::iterator p =A.begin();p!=A.end();++p){
        cout<<*p<<"";
    }
    cout<<endl;
    return 0;
} 
  • 2.映射和多重映射
    基于某一个类型Key的键集的存在,提供对T类型数据的高效检索。映射(map)不支持副本键,多重映射(multimap)支持。键的本身是不能被修改的,除非删除
    集合和映射的区别:集合的键和值是key类型的,而map键和值是一个pair结构中的两个分量.
#include<iostream>
#include<map>
using namespace std;
int main(){

    //  键     值   排序方式 
    map<char,int,less<char> >map1;
    map<char,int,less<char> >::iterator mapIter;
    map1['c']=3;
    map1['d']=4;
    map1['b']=2;
    map1['a']=1;

    for(mapIter=map1.begin();mapIter!=map1.end();++mapIter){
        cout<<""<<(*mapIter).first<<":"<<(*mapIter).second;
    }

    map<char,int,less<char> >::const_iterator ptr;
    ptr=map1.find('d');
    cout<<endl<<""<<(*ptr).first<<"键对应于值:"<<(*ptr).second;

    map<int,int,less<int> >map2;
    map2[1]=2;
    map2[3]=4;
    map<int,int,less<int> >::const_iterator ptr2;
    ptr2 = map2.find(1);
    cout<<(*ptr2).first<<"键对应值:"<<(*ptr).second;

    return 0;
}

容器适配器

  • 1.栈
    常用操作:
    push(x);
    pop();
    top();
    empty();
    size();
  • 2.队列
    常用操作:

    front();
    back();
  • 3.优先级队列
    底层使用vector或deque实现,当添加元素时,按照优先顺序插入。默认情况下元素的比较是通过比较函数对象less<<>>执行.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值