zoukankan      html  css  js  c++  java
  • C++程序设计——知识点总结

    C++程序设计课程的总结,方便以后快速查阅和复习

    Week 2 从C走进C++


    函数指针

    函数名是函数的入口地址,指向函数的指针称为“函数指针”。

    比如,qsort库函数:

    void qsort(void *base, int nelem, unsigned int width,
        int ( * pfCompare)( const void *, const void *)); 
    

    其中的第四个参数,就是一个函数指针,pfCompare:比较函数的地址。

    命令行参数

    int main(int argc, char *argv[]){
        ...
    }
    

    argc:命令行参数的个数
    argv:指针数组,argv[0]指向第一个命令行参数,argv[1]指向第二个命令行参数...

    位运算

    & ^ ~ << >>
    按位与 按位或 按位异或 按位非 左移 右移

    异或运算实现a,b值交换:

    a = a ^ b;
    b = b ^ a;
    a = a ^ b; 
    

    引用

    变量的引用,等价于这个变量,相当于一个别名:

    int n = 4;
    int &r = n;
    

    const关键字和常量

    在定义前加上const关键字,就代表这是个常量(常量,常量指针,常引用),不可变的东西。

    const int *p = &n; //常量指针

    动态内存分配

    用new分配内存,delete释放内存

    分配变量:

    int * p = new int;
    * p = 5;
    delete p;
    

    分配数组:

    int * p = new int[20];
    p[0] = 1;
    delete [ ] p;
    

    内联函数,函数重载,缺省参数

    • 内联函数:函数的定义前加关键字inline。

    • 函数重载:名字相同,参数个数或类型不同。

    • 缺省参数:定义函数时,让最右边的几个参数有缺省值,这样在调用的时候相应位置可以不写参数。

      void func( int x1, int x2 = 2, int x3 = 3) { }

    类的可访问范围

    关键字:private,public,protected,缺省为私有成员

    Week 3 类和对象


    内联成员函数和重载成员函数

    • 内联成员函数:inline + 成员函数,在类定义内部
    • 成员函数的重载和参数缺省,使用缺省参数时注意避免有函数重载时的二义性

    构造函数

    • 成员函数的一种,名字与类名相同,可以有参数,不能有返回值
    • 用来对对象进行初始化
    • 若没有自定义,则默认生成无参构造函数

    复制构造函数

    用来复制的构造函数,这样一个参数:同类对象的引用

    Complex( const Complex & c ) {...} //可以没有const

    • 编译器会自动生成复制构造函数用于复制
    • 若自定义了,则默认的复制构造函数不存在
    • 复制构造函数起作用的三种情况:
      1. 用一个对象初始化同类的另一个对象
      2. 一个包含类A为参数的函数被调用时
      3. 函数的返回值是对象,函数返回时

    类型转换构造函数

    和类型转换函数不是一个名词的样子,这个类型转换构造函数,其实就是一个构造函数而已,但是像具有类型转换的功能,把其他的东西转换为本类,比如:

    Complex(int i){
        real = i; imag = 0;
    }
    

    析构函数

    • 名字与类名相同,在前面加 ~,没有参数和返回值,比如:~String();
    • 一个类最多只有一个析构函数
    • 对象消亡时自动调用
    • 若自定义了,则不生成缺省析构函数
    • delete运算可导致析构函数调用,比如:delete pTest; delete [] pTest;

    静态成员变量和静态成员函数

    • 在成员变量或成员函数的前面加关键字static
    • 普通成员变量每个对象各自有各自的,而静态成员变量一共就一份,大家共享,所以没有对象也能访问,想个全局变量似的
    • 静态成员函数中,不能访问非静态的东西

    成员对象和封闭类

    • 成员对象:类的成员变量是另一个类的对象
    • 封闭类:包含成员对象的类

    封闭类里包含了其他的类的对象,所以生成封闭类对象时,应该也要知道里边的对象该怎么初始化

    在定义封闭类的构造函数时,添加初始化列表:

    CMyClass::CMyClass(int x, int y) : m_y(y), m_x(m_y){...}

    调用顺序:

    • 对象生成时
      1. 成员对象的构造函数
      2. 封闭类的构造函数
    • 成员对象的构造函数调用顺序
      • 和成员对象在类中的说明顺序一致
      • 与初始化列表无关
    • 对象消亡时
      1. 封闭类的析构函数
      2. 成员对象的析构函数
    • 析构与构造调用顺序相反

    友元

    • 友元函数:在一个类里边,用friend加到前面来声明一个函数(这个函数可以是另一个类的成员函数),这个函数就是该类的友元函数,可以访问该类的私有成员

      class A { friend void B::function(); };

    • 友元类:声明一个类是本类的友元,那么那个类的成员函数都可以访问本类的私有成员

      class A { friend class B; };

    this指针

    指向成员函数当前所作用的对象

    静态成员函数不能使用this指针,因为静态成员函数并不具体作用于某个对象

    常量对象、常量成员函数和常引用

    • 常量对象:不希望这个对象被修改,在前面加const关键字

      const Demo Obj;

    • 常量成员函数:在成员函数说明后面加const关键字,它不能修改其所作用的对象,所以它不能修改成员变量的值。也不能调用同类的非常量成员函数(静态成员变量和静态成员函数除外,因为静态的东西不算某个对象所自有)
      (有const的和没const的函数,其他一样,算重载)

      void Sample::Get Value() const

    • 常引用:不能通过常引用修改其引用的变量,在前面加const关键字

      void Printf Obj( const Sample & o)
      函数的参数需要传递对象的时候,直接传递对象需要调用复制构造函数,效率低,所有可以用引用(或指针),但是这样有危险(函数有可能一不小心对引用的对象进行修改),所以呢就加一个const,这样的话一旦想修改就会编译错误了

    Week 4 运算符重载


    运算符重载的基本概念

    • C++预定义了一些运算符,用于基本数据类型的运算
    • 对运算符进行重载,让自定义的类也能使用运算符,比较方便,运算符本质上就是函数
    • 运算符可以被重载为普通函数,也能重载为类的成员函数
      • 重载为普通函数

          Complex operator+ (const Complex & a, const Complex & b) {
              return Complex( a.real+b.real, a.imaginary+b.imaginary); 
          }
        

        这时,仅仅是对 '+' 这个运算符的功能进行了扩充,参数个数还是本身的运算符目数

      • 重载为成员函数

          Complex Complex::operator+(const Complex & operand2) {
              return Complex( real + operand2.real, imaginary + operand2.imaginary ); 
          } // 在类里边还得声明,或者直接在类中定义,这样就是类的成员函数了
        

        这时,参数个数为本身的运算符目数减一,因为现在执行这个成员函数的对象本身不需要放在参数里面了

    赋值运算符的重载

    • 赋值运算符“=”只能重载为成员函数
    • 对“=”进行重载,就能自定义把一个类型的对象直接赋值给另一个类型的对象

    比如:
    将一个字符串复制给另一个字符串,直接使用“=”,算是浅复制(指向字符串的指针之间的复制),我们可以重载“=”实现深复制(指针所指向的字符串内容间的复制)
    返回值可以是 String &,这样会比较方便

    运算符重载为友元函数

    有时,成员函数不能满足使用要求,普通函数又不能访问类的私有成员,这时可以重载为友元

    流插入运算符和流提取运算符的重载

    cout << 5 << "abc" 这种写法是因为在iostream里对“<<”进行了重载

    自增自减运算符的重载

    自增自减本来都是一元运算符,重载时为了区分吧,然后前置运算符作为一元运算符重载T operator++();,后置运算符作为二元运算符重载T operator++(int);,仅仅只是表面上多一个参数。

    • int可作为一个类型强制转换运算符被重载:

      operator int(){ return n;},然后就能这些写了:(int) s;等效于s.int()

    运算符重载的注意事项

    • 不允许定义新的运算符
    • 不改变运算符的优先级
    • 最好符合日常习惯
    • 以下运算符不能被重载: . * :: ?: sizeof
    • 运算符(),[],->, = ,必须声明为类的成员函数

    Week 5 继承与派生


    继承与派生

    class 派生类名: public 基类名{...};
    派生类对象的体积,等于基类对象的体积,再加上派生类对象自己的成员变量的体积。在派生类对象中,包含着基类对象,而且基类对象的存储位置位于派生类对象新增的成员变量之前。

    继承关系与复合关系

    • 继承:“是”关系
      B是基类A的派生类,则“一个B对象也是一个A对象”
    • 复合:“有”关系
      一个对象中的有一个成员变量是另一个类的对象

    基类/派生类同名成员与Protected关键字

    void derived::access() {
        j = 5;//error(派生类没有变量j)
        i = 5;    //引用的是派生类的 i
        base::i = 5; //引用的是基类的 i
        func();  //派生类的
        base::func(); //基类的 
    } 
    

    派生类的成员函数可以访问当前对象的基类的保护成员

    派生类的构造函数

    FlyBug :: FlyBug (int legs, int color, int wings): Bug(legs, color) {
        n Wings = wings; 
    } 
    
    • 派生类对象包含基类对象
    • 执行派生类构造函数之前, 先执行基类的构造函数(析构函数相反)
    • 除了上面的那个显式方式,还可以是隐式方式(派生类的构造函数中, 省略基类构造函数,自动调用基类的默认构造函数)
    • 顺序:基类构造函数( ightarrow)成员对象类的构造函数( ightarrow) ... (析构函数相反)

    public继承的赋值兼容规则

    如果是public(其他不行):

    1. 派生类对象可以赋值给基类对象b = d;
    2. 派生类对象可以初始化基类引用 base &br = d;
    3. 派生类对象的地址可以赋值给基类指针base *pb = & d;

    Week 6 虚函数与多态


    虚函数和多态

    • 虚函数

        class base {
            virtual int get() ; 
        }; 
        int base::get()  //函数声明时加virtual就行
        { }
      
    • 多态的表现形式1:
      通过基类指针调用基类与派生类中同名的虚函数时,
      若,指针指向的是基类对象,则调用基类的虚函数
      若,指向的是派生类的对象,则调用派生类虚函数

    • 多态的表现形式2:
      用基类引用来实现,和上面的基本一样

    • 多态的好处:增强程序的可扩充性

      比如,很多的类都继承于同一个基类,它们有一些类似的操作,需要使用这些类的对象们,如果没有多态,那么代码的每一个语句都需要具体到哪个类,这样需要写很多类似的重复性代码,增加新的类时很不方便,而使用多态的话,不需要在类的代码里明确到底是对那个类对象进行操作,全都使用基类指针或引用,实际使用时让这个指针指向谁就操作谁, 这样就方便多了。

    多态实现原理

    “多态”的关键在于通过基类指针或引用调用一个虚函数时,编译时不确定到底调用的是基类还是派生类的函数,运行时才确定 —— 这叫“动态联编”。

    多态的函数调用语句被编译成一系列根据基类指针所指向的(或基类引用所引用的)对象中存放的“虚函数表”的地址,在虚函数表中查找虚函数地址,并调用虚函数的指令。

    虚析构函数

    如果不是虚的析构函数,那么使用基类指针删除派生类对象时,只调用基类的析构函数,这样派生类对象实际上还没被删掉。所以我们这样:把基类的析构函数声明为virtual(这时派生类的析构函数就自动也是虚函数了),这时使用基类指针删除派生类对象,会首先调用派生类的析构函数,然后调用 基类的析构函数。

    • 如果定义了虚函数,最好将析构函数也定义为虚函数
    • 不允许有虚的构造函数

    纯虚函数和抽象类

    • 纯虚函数:没有函数体的虚函数virtual void Print() = 0;
    • 抽象类:包含纯虚函数的类(只能用来派生新类,不能创建对象)
      • 成员函数里可以调用纯虚函数
      • 构造/析构函数里不能调用纯虚函数
      • 实现了所有纯虚函数的派生类才能称为非抽象类

    Week 7 文件操作和模板


    文件操作

    • ifstream,ofstream,fstream 用于文件操作,统称为文件流类
    • 基本流程:打开文件(连接,使用方式)( ightarrow)读写文件( ightarrow)关闭文件
    • ofstream out File(“clients.dat”, ios::out|ios::binary); //打开文件out 删除原有内容, app 在尾部添加 binary 以二进制格式
    • 或者 ofstream fout; fout.open( “test.out”, ios::out|ios::binary );
    • 判断打开是否成功if(!fout) { cerr << “File open error!”<<endl; }
    • 读指针/写指针/读写指针,指向哪里就在哪进行读写操作。tellp(); seekp(); seekg(); ...
      fout.write( (const char *)(&x), sizeof(int) );
      fin.read( (char *)(&x), sizeof(int) );

    函数模板

    • 泛型程序设计,算法实现时不指定具体要操作的数据的类型,包括函数模板、类木板

    • 比如,交换两个变量的值,编译器会根据调用的情况生成相应数据类型的函数

        template <class T> 
        void Swap(T & x, T & y)  {   
            T tmp = x;   
            x = y;   
            y = tmp; 
        } 
      
    • 编译器先找普通函数,再去找模板函数,再找实参自动类型转换后能匹配的普通函数,如何还找不到就报错

    类模板

    • Pair类模板:

        template <class T1, class T2> 
        class Pair{     
        public:   
            T1 key;    //关键字   
            T2 value;    //值   
            Pair(T1 k,T2 v):key(k),value(v) { };   
            bool operator < (const Pair<T1,T2> & p) const;  
        };
        template<class T1,class T2> 
        bool Pair<T1,T2>::operator<( const Pair<T1, T2> & p) const {
            return key < p.key;   
        } 
      
    • Pair类模板的使用

        int main() {    
            Pair<string, int> student("Tom",19);  //实例化出一个类 Pair<string, int>    
            cout << student.key << " " << student.value;     
            return 0;  
        } 
      
    • 类模板的实例化得到的类叫模板类

    • 类模板的参数声明中可以包括非类型参数:
      template <class T, int elements Number> 非类型参数: 用来说明类模板中的属性

    • 类模板与继承:
      类模板派生出类模板,模板类派生出类模板,普通类派生出类模板,模板类派生出普通类

    string类

    • 初始化
      • string s1("Hello");
      • string s2(8, 'x');
      • string month = "March";
    • 可以将字符赋值给string对象s = 'n'
    • 长度 s.length()
    • 流读取运算符'cin >> string Object;'
    • getline(cin, s);
    • string的赋值和连接
      • 赋值s2 = s1;
      • 复制s3.assign(s1);
      • 部分复制s3.assign(s1, 1, 3);
      • 单个字符复制s2[5] = s1[3] = 'a';
      • s1.at(i),会做范围检查
      • 用+连接 s1 += s2;
      • s1.append(s2);
    • 比较string
      • 关系运算符== , >, >=, <, <=, !=
      • int f1 = s1.compare(s2);
    • 子串 s2 = s1.substr(4,5);
    • 交换 s1.swap(s2);
    • capacity(); maximum_size(); length(); size(); empty(); resize()
    • find(); rfind(); find_first_of(); find_last_of(); find_first_not_of(); find_last_not_of();
    • erase(); replace(); insert();
    • c_str(); data(); copy();

    输入输出

    • 类:istream, ostream, ifstream, ofstream, iostream, fstream.
    • 标准流对象:cin, cout, cerr, clog
    • 输出重定向:
      freopen("test.txt","w",stdout); //将标准输出重定向到 test.txt文件
    • 输入重定向:
      freopen(“t.txt”,“r”,stdin); //cin被改为从 t.txt中读取数据
    • 判断输入流结束:
      while(cin>>x){...}
    • 键盘 Ctrl+Z 代表输入流结束
    • getline:
      istream & getline(char * buf, int buf Size);
      istream & getline(char * buf, int buf Size,char delim);
      if(!cin.getline(…))
    • bool eof(); 判断输入流是否结束
    • int peek(); 返回下一个字符,但不从流中去掉
    • istream & putback(char c); 将字符ch放回输入流
    • istream & ignore( int n Count = 1, int delim = EOF ); 从流中删掉最多n Count个字符,遇到EOF时结束

    Week 8 标准模板库 STL -1


    概述

    • 泛型程序设计:使用模板的程序设计法。
    • 容器:类似于类模板
      1. 顺序容器(元素没有按值进行排序):vector(动态数组),deque(双向队列),list(双向链表)
      2. 关联容器(元素是排序的,平衡二叉树):set(集合), multiset(允许相同元素),map(每个元素包含first和second),multimap(允许相同的first)
      3. 容器适配器:stack(栈),queue(队列),priority_queue(优先级队列)
    • 迭代器:类似于指针
      vector::const_iterator i; //常量迭代器
      for( i = v.begin();i != v.end();++i )
      cout << * i << ",";
      reverse_iterator(反向迭代器),iterator(非常量迭代器)
      • 容器上的迭代器类别
        • 随机访问:vector,deque
        • 双向:list,set/multiset,map/multimap
        • 不支持迭代器:stack,queue,priority_queue
    • 算法: 类似于函数模板
      • find():p = find(v.begin(),v.end(),3);返回一个迭代器,指向找到的元素,或者last
    • 顺序容器和关联容器都有的成员函数:
      begin,end,rbegin,rend,(返回迭代器),erase,clear
    • 顺序容器常用成员函数:
      front,back,(返回元素引用),push_back,pop_back,erase
    • ”x和y相等“有时等价于”x==y为真“,有时等价于”x小于y和y小于x同时为假“

    vector

    可变长动态数组,#include <vector>,所有STL算法都支持

    • 初始化:

      • vector();
      • vector(int n);
      • vector(int n, const T & val);
      • vector(iterator first, iterator last);
    • 常用成员函数

    成员函数 作用
    void pop_back(); 删除容器末尾的元素
    void push_back(const T & val); 将val添加到容器末尾
    int size(); 返回容器中元素的个数
    T & font(); 返回容器中第一个元素的引用
    T & back(); 返回容器中最后一个元素的引用

    list和deque

    • list容器还支持:push_front,pop_front,sort,remove,unique,merge,reverse,splice
    • list容器的sort函数(由于list不支持完全随机访问,不能用STL的sort函数)
      list<T> classname classname.sort(compare); classname.sort();
    • deque除了所有适用于vector的操作,还有push_front和pop_front

    函数对象

    若一个类重载了运算符“()”,则该类的对象就成为函数对象
    以下模板可以用来生成函数对象:equal_tp,greater,less ...头文件
    lst.sort(greater<int>()); //greater<int>()是个对象

    Week 9 标准模板库 STL -2


    set和multiset,map和multimap

    • set,multiset,map,multimap还支持:find,lower_bouond,upper_bound,equal_range,count,insert
    • pair模板:pair模板类的对象包含first和second两个成员变量,map/multimap放着的就是这些
    • multiset:
      template<class Key, class Pred = less<Key>, class A = allocator<Key> >
      class multiset { …… };
    • set:
      template<class Key, class Pred = less<Key>, class A = allocator<Key> >
      class set { … }
    • multimap:
      template<class Key, class T, class Pred = less<Key>,class A = allocator<T> >
      class multimap { …...pedef pair<const Key, T> value_type; …….}; //Key 代表关键字的类型
    • map
      template<class Key, class T, class Pred = less<Key>,class A = allocator<T> >
      class map { ….typedef pair<const Key, T> value_type; …….};//关键字(first)各不相同
    • map的[]成员函数,e.g. pairs[key]

    容器适配器

    用某种顺序容器来实现,让已有的顺序容器以栈/队列的方式工作,stack,queue,priority_queue

    • 三个成员函数
      • push:添加元素
      • top:返回栈顶部或队头元素的引用
      • pop:删除一个元素
    • STL的各种排序,查找,变序等算法都不适合容器适配器

    STL算法

    STL算法大致可以分为一下七类:

    1. 不变序列算法:
      不修改,适用于顺序容器和关联容器,O(n)
      min,max,min_element,max_element,for_each,count,count_if,find,find_if,find_end,find_first_of,adjacent_find,search,search_n,equal,mismatch,lexicographical_cpmpare
    2. 変值算法:
      会修改,修改的区间不可以是属于关联容器的
      for_each,copy,copy_backward,transform,swap_ranges,fill,fill_n,generate,generate_n,replace,replace_if,replace_copy,replace_copy_if
    3. 删除算法:
      删除某些元素,O(n),删除是指:将删掉的元素看作空位,然后留下的元素前移补上,最后没被补上的空位维持其原来的值不变
      remove,remove_if,remove_copy,remove_copy_if,unique,unique_copy
    4. 变序算法:
      改变顺序不改变值,不适用于关联容器,O(n)
      reverse,reverse_copy,rotate,rotate_copy,next_permulation,prev_permulation,random_shuffle,partition
    5. 排序算法:
      一般是O(nlog(n)),需要随机访问迭代器,不适用于关联容器和list
      sort,stable_sort,partial_sort,partial_sort_copy,nth_element,make_heap,push_heap,pop_heap,sort_heap
    6. 有序区间算法
      要求区间已经排号序,需要随机访问迭代器,不能用于关联容器和list
      binary_search,includes,lower_bound,upper_bound,equal_range,merge,set_union,set_intersection,set_difference,set_symmetric_difference,inplace_merge
    7. 数值算法...
    • 大多数重载的算法都有两个版本,比如:

      • iterator min_element(iterator first, iterator last);
      • iterator min_element(iterator first, iterator last, Pred op);//表达式op(x, y)的返回值来判断x与y的大小
    • bitset:template<size_t N> class bitset{ ...... };比如

      • bitset<40> bst;一个由40位组成的对象

    作者:[rubbninja](http://www.cnblogs.com/rubbninja/) 出处:[http://www.cnblogs.com/rubbninja/](http://www.cnblogs.com/rubbninja/) 关于作者:目前主要研究领域为机器学习与无线定位技术,欢迎讨论与指正!
  • 相关阅读:
    MySQL数据库备份
    执行SDK的aapt报错./aapt: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by ./aapt)
    ftp删除目录和文件,目录下有文件删除提示【550 Remove directory operation failed.】
    Spring mvc接收中文参数值乱码(tomcat配置问题)
    python3获得命令行输入的参数
    Java反射、动态加载(将java类名、方法、方法参数当做参数传递,执行方法)
    java定义object数组(可以存储String或int等多种类型)
    java方法中增加不固定参数
    ibatis和myBatis打印sql语句的log4j配置文件
    spring依赖注入之手工装配
  • 原文地址:https://www.cnblogs.com/rubbninja/p/4925633.html
Copyright © 2011-2022 走看看