模板

  1. use explicit class specialization:
    template< > class myClass< > {}
  2. 模板类和函数重载的区别:
    Overloading is multiple function doing similar operation
    Template is multiple function doing identical operations
  3. 如果在模板类中声明静态变量,每个实例都会有自己的静态变量
    看个例子
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    template <typename T>
    void test(const T &x)
    {
    static int count = 0;
    cout << "x = " << x << " count = " << count << endl;
    ++count;
    return;
    }
    int main()
    {
    test<float>(2.0);
    test<int>(3);
    test<int>(3);
    test<double>(2.2);
    }
    //x = 2 count = 0
    //x = 3 count = 0
    //x = 3 count = 1
    //x = 2.2 count = 0
  4. 再看一个例子
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #include <iostream>
    #include <map>
    using namespace std;
    std::map<char *, int> m;
    const int MAX_SIZE = 100;
    int main()
    {
    char str[MAX_SIZE];
    for (int i = 0; i < 10; i++)
    {
    std::cin >> str;
    m[str] = i;
    }
    std::cout << m.size() << std::endl;
    }
    如果输入10个字符串,输出是1
    因为map中的键类型是char*,由于str是一个字符数组,每次输入新的字符串时,str的内容被覆盖,但是str的地址保持不变,因此map实际上一直在使用同一个键,并不断更新与该键关联的值,无论输入多少个不同的字符串,map中只会有一个元素,最终输出的m.size()是1,而不是输入的字符串数量
  5. vector<int> v = 1是不合法的,没有接受单个整数作为参数的构造函数
    vector<int> v = (10, 1)和上面一样
  6. 迭代器的分类:输入迭代器,前向迭代器,双向迭代器
  7. string s;实际上初始化了一个空字符串,不能用下标操作符去修改里面的字符
  8. getline(cin, s),读取直到遇到下一个换行符
    cin >> n,如果用户输入一个字符并按下回车,回车符仍然留在输入流中,如果此时执行getline(cin, s),读到换行符,直接停止读取,返回一个空字符串
  9. get()getline()的区别:
    前者不消耗换行符,如果连续使用,下一个get()会立即遇到上一个留下的换行符并停止读取
    后者消耗换行符,如果连续调用,每次调用都会从下一行开始读取

异常处理

  1. 异常是程序运行期间抛出的问题,处理异常可以避免程序不正常终止
  2. 如果在目标位置没有找到要打开的文件,将会产生异常
  3. 如果要捕捉异常,需要创建一个对象
    多个捕获块可以合并成一个
    e.g.: IOExceptions处理I/O异常
    ClassNotFoundException处理未定义类异常
    UnsupportedEncodingException处理不支持的字符编码异常
  4. 如果一个捕获块接受不止1个异常,那么catch的参数是final(什么意思?)
  5. 如果类产生多个异常,他们的catch block必须被定义,以保证与类相关的异常都由程序代码处理,并且不会异常终止
  6. 传统函数返回需要一级一级返回,但异常处理可以直接到达能够处理异常的地方
    异常处理机制语法如下
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    //异常发生第一现场,抛出异常
    void function( ){
    //... ...
    throw /*表达式*/;
    //... ...
    }
    //在需要关注异常的地方,捕捉异常
    try{
    //程序
    function(); //把function至于try中
    //程序
    }catch(/*异常类型声明*/){ //比如只写一个int
    //... 异常处理代码 ...
    }catch(/*异常类型 形参*/){ //形参将会取得抛出的值
    //... 异常处理代码 ...
    }catch(...){ //抛出的其它异常类型,可以接收任意类型
    //
    }//如果没有catch(...) 并且没有catch子句与抛出的异常类型匹配 程序会直接中断报错
    throw后面可以跟任何表达式,整数、指针、字符常量、浮点数等,通过该操作可以创建一个异常对象并抛出
    如果catch里一直找不到匹配,缺省功能是调用abort终止程序
  7. 异常接口声明:void f(int x) throw (float, string *, int) { }
    在函数声明中列出可能抛出的所有异常类型,如果抛出未声明的异常,可能导致程序终止
    如果不声明,函数可以抛出任何类型的异常
    如果不想抛出异常,throw()
  8. 异常接收:
    对于基本类型的异常,使用对应类型catch捕获即可,但类型要严格匹配,const修饰也要对应好,指针就是指针,string就是string
    当异常类型是一个类对象时,不管抛出匿名对象还是局部变量,程序会生成一个匿名对象,当catch是普通参数时,程序会调用拷贝函数;也可以用引用和指针接收,但注意,引用和普通的形参传值不共存,否则同时捕捉,编译器不知道是哪个

文件

  1. 打开一个文件就是将整个文件与一个流关联;关闭文件就是取消关联
  2. 打开文件
    ofstream ofile; ofile.open("D:\a.txt", ios::binary)
    fstream iofile; iofile.open("a.txt", ios::ate)
    ifstream ifile("D:\a.txt", ios::binary)
  3. 打开文件的目的是使文件对象与磁盘文件建立联系,但文件读写过程中程序不会直接和磁盘文件进行数据交换
    关闭文件的目的包括将输出的数据写入硬盘文件、释放内存中的文件对象等
  4. ios是基础类,istream、ostream是ios的直接派生类
    iostream是istream和ostream的多重继承来的类,不是直接从ios继承的
    strstreambase不是ios的直接派生类,它处理基于字符串的流
  5. 对磁盘文件进行操作时,以ios::out模式打开的文件,可实现创建一个可以写入的、新的空文件;如果文件已经存在,则删除以前的内容再写入新数据
    ifstream类对象默认打开方式ios::in,ostream类对象默认打开方式ios::out
    ios::app追加模式,用于输出操作,确保写入的数据总是追加到文件末尾
    ios::trunc打开文件并清空,之后可以进行写入
  6. 文件的打开方式可以组合使用