• Essential C++学习笔记备忘


    提示:本文是一篇个人读书笔记,并不是对原书内容的系统总结整理,可能对作者以外的读者没有太大的参考意义。

    第一章 C++编程基础

    1. 构造函数语法(P8),除了一般的等式初始化外的另一种初始化方法

      int num_tries(0)

    2.case标签的向下穿越(P19),比较后会一直执行符合的case语句以及下面的所有语句。

    3.vector的两种初始化方式(P24-25)

      单个元素逐一指定;利用一个已经初始化的array赋值

    4.while(infile>>name)何时结束?(P32)

      读到文件尾端,infile>>name返回false

    5.cin中的setw()(习题,P207)

    第二章 面向过程的编程风格

    1.传值、传引用(&,P45)、传地址(*,P47)调用,即使不需要修改原数值,也可以使用后两者获得比第一种快的速度,原因是不需要对整个对象进行复制(P47)。后两者主要差异是使用时的用法不同。

    2.函数位于程序栈(P48),动态分配(new)位于堆(P49)

    3.delete数组方式(P50): delete []pia;

    4.函数默认值设定时,不能将引用设置为0,它必须代表某个对象。(P51)

    5.模板函数用法(P59)

    6.头文件(P63):inline函数应定义于头文件(P63);const对象(非指针)只在文件内作用(P64)。

    7.习题2.6注意把max函数换个名字,否则与std命名空间冲突。

    第三章 泛型编程风格

    1.iterator定义形式(以vector为例)(P74):

      vector<string> svec;

      vector<string>::iterator iter = svec.begin();

     衍生的const形式:

      const vector<string> cs_vec;

      vector<string>::const_iterator = cs_vec.begin();

    2.泛型函数:以find()为例(P75)

      利用了模板函数写成,能够支持不同容器的使用。

    3.三种序列式容器对象(P78):list、vector、deque

    4.设计泛型算法的演化(P83~89):这部分如果只读书读不懂,还是按照演化过程把代码写一遍比较好理解。P93~94是对这一节的进一步扩充。

    5.勘误:习题3.2(P221)在vector<elemType>前需要加typename。

    第四章 基于对象的编程风格

    1.class的无参数初始化是T t而不能用T t(),后者是个函数定义。

     T t=8相当于调用单一参数的构造函数。(P105)

    2.第二种构造函数constructor初始化语法:成员初值表member initialization list(P106)

      在习题里提到的,类定义里,构造函数默认参数列表还能这么写:Triangular(int=1,int=1)

    3.member function的const修饰符:告诉编译器其不会更动其调用者。放置于参数表后。(P110)

      P111提供了member function的const版本和非const版本,并说明了如何分别调用二者。

      更进一步的补充是mutable关键字,告诉编译器改变其所修饰的变量不会改变类的常数性,因此可以在用const修饰的member function中修改。

    4.this指针会由编译器自动地将其加到每一个member function的参数列表中,函数体内也会发生这种转换。(P114)

    5.只有在member function不存取任何non-static members的条件下才能够被声明为static(P116),在类外定义时不需要再加static(P117)

     类的static成员变量必须在文件中初始化。

    6.附注:本章正文代码实际上是自己编写了个只适用于Triangular类的iterator,并对它重载了*、++等运算符。这些内容体现在下面的代码中,大部分是按照原书正文写的,小部分是按照原书提供的源码补充的。

    chapter4
    /*
     * =====================================================================================
     *       Filename:  ConstAndMutableClass.cpp
     *    Description:  
     *        Version:  1.0
     *        Created:  2013年04月16日 17时29分08秒
     *         Author:  wuyue (wy), vvuyve@gmail.com
     *        Company:  UESTC
     * =====================================================================================
     */
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <string>
    using namespace std;
    
    
    class Triangular_iterator
    {
    public:
        Triangular_iterator(int index):_index(index-1){}
        bool operator==(const Triangular_iterator& ) const;
        bool operator!=(const Triangular_iterator& ) const;
        int operator*() const;
        Triangular_iterator& operator++();
        Triangular_iterator operator++(int);
    private:
        void check_integrity() const;
        int _index;
    };
    
    //    notice:
    //1.kinds of constructor,P105
    //2.constructor with member initialization list,P106
    //3.function with const after its parameter list,P110
    //4.mutable,P112
    //5.static functions,P116
    class Triangular {
        friend class Triangular_iterator;
    public:
        //const member functions
        int length() const {return _length;}
        int beg_pos() const {return _beg_pos;}
        int elem(int pos) const;
        
        //non-const member functions
        void length(int nlen) {_length = nlen;}
        void beg_pos(int npos) {_beg_pos = npos;}
        bool next(int &val) const;
        void next_reset() const {_next = 1;}
        
        //constructor
        Triangular(int=1,int=1);
        //Triangular(int l=1, int bp=1) is usually form
        Triangular(const Triangular &rhs);
        Triangular& operator=(const Triangular &rhs);
        Triangular& copy(const Triangular &rhs);
        static bool is_elem(int);
        static void gen_elements(int length);
        static void gen_elems_to_value(int value);
        static void display(int length, int beg_pos, ostream &os = cout);
        typedef Triangular_iterator iterator;
        Triangular_iterator begin() const
        {
            return Triangular_iterator(_beg_pos);
        }
        Triangular_iterator end() const
        {
            return Triangular_iterator(_beg_pos+_length);
        }
    private:
        int _length;
        int _beg_pos;
        mutable int _next;
        static const int   _max_elems = 1024;
        static vector<int> _elems;
    };
    
    
    //a static member must be initalized
    //whether it in its class or not
    vector<int> Triangular::_elems;
    
    int Triangular::elem(int pos) const
        {return _elems[pos-1];}
    
    bool Triangular::next(int &value) const
    {
        if(_next<_beg_pos+_length-1)
        {
            value = _elems[_next++];
            return true;
        }
        return false;
    }
    
    
    Triangular&
    Triangular::
    operator=( const Triangular &rhs )
    {
        if ( this != &rhs ) { 
            _length = rhs._length;
            _beg_pos = rhs._beg_pos;
            _next = 1;
        }
        return *this;
    }
    
    //Member Initialization List,P106
    Triangular::Triangular(const Triangular &rhs)
        :_length(rhs._length),_beg_pos(rhs._beg_pos),_next(rhs._next)
    {}
    
    Triangular::Triangular(int len,int beg_pos)
        : _length(len>0?len:1),
        _beg_pos(beg_pos>0?beg_pos:1)
    {
        _next=_beg_pos;
        int elem_cnt = _beg_pos + _length;
        if(_elems.size()<elem_cnt)
            gen_elements(elem_cnt);
    }
    
    
    bool Triangular::is_elem(int value)
    {
        if(!_elems.size()||_elems[_elems.size()-1]<value)
            gen_elems_to_value(value);
        vector<int>::iterator found_it;
        vector<int>::iterator end_it = _elems.end();
        found_it = find(_elems.begin(),end_it,value);
        return found_it!=end_it;
    }
    
    void Triangular::
    gen_elems_to_value( int value )
    {  
        int ix = _elems.size();
        if ( !ix ){
            _elems.push_back( 1 );
        ix = 1;
       }
    
        while ( _elems[ ix-1 ] < value && ix < _max_elems )
        {
        //cout << "elems to value: " << ix*(ix+1)/2 << endl;
            _elems.push_back( ix*(ix+1)/2 );
                ++ix;
        }
    
        if ( ix == _max_elems )
            cerr << "Triangular Sequence: oops: value too large "
                << value << " --  exceeds max size of "
                << _max_elems << endl;
    }
    
    void Triangular::
    gen_elements( int length )
    {
        if ( length < 0 || length > _max_elems ){
            cerr << "Triangular Sequence: oops: invalid size: "
                 << length << " -- max size is "
                 << _max_elems << endl;
            return;
        }
       
        if ( _elems.size() < length )
        {
            int ix = _elems.size() ? _elems.size()+1 : 1;
            for ( ; ix <= length; ++ix )
                  _elems.push_back( ix*(ix+1)/2 );
        }
    }
    
    Triangular& Triangular::copy(const Triangular &rhs)
    {
        if(this!=&rhs)
        {
            _length=rhs._length;
            _beg_pos=rhs._beg_pos;
            _next=rhs._next;
        }
        return *this;
    }
    
    //operator relaoded
    inline bool Triangular_iterator::
    operator==(const Triangular_iterator &rhs) const
        {return _index == rhs._index;}
    
    inline bool Triangular_iterator::
    operator!=(const Triangular_iterator &rhs) const
        {return !(*this == rhs);}
    
    class iterator_overflow{};
    
    inline void Triangular_iterator::
    check_integrity() const
    {
        if(_index>= Triangular::_max_elems)
            throw iterator_overflow();
        if(_index>=Triangular::_elems.size())
            Triangular::gen_elements(_index + 1);
    }
    
    inline int Triangular_iterator::
    operator*() const
    {
        check_integrity();
        return Triangular::_elems[ _index ]; 
    }
    
    inline Triangular_iterator& Triangular_iterator::
    operator++()
    {
        ++_index;
        check_integrity();
        return *this;
    }
    
    inline Triangular_iterator Triangular_iterator::
    operator++(int)
    {
        Triangular_iterator tmp = *this;
        ++_index;
        check_integrity();
        return tmp;
    }
    
    void Triangular::
    display( int length, int beg_pos, ostream &os )
    {
        if ( length <= 0 || beg_pos <= 0 ){
            cerr << "invalid parameters -- unable to fulfill request: "
                << length << ", " << beg_pos << endl;
            return;
        }
    
        int elems = beg_pos + length - 1;
        if ( _elems.size() < elems )
            gen_elements( elems );
        for ( int ix = beg_pos-1; ix < elems; ++ix )
            os << _elems[ ix ] << ' ';
    }
    
    ostream& operator<<(ostream &os,const Triangular &rhs)
    {
        os<<"("<<rhs.beg_pos()<<","<<rhs.length()<<")";
        rhs.display(rhs.length(),rhs.beg_pos(),os);
        return os;
    }
    
    istream& operator>>(istream &is,Triangular &rhs)
    {
        char ch1,ch2;
        int bp,len;
        is>>ch1>>bp>>ch2>>len;
        rhs.beg_pos(bp);
        rhs.length(len);
        rhs.next_reset();
        return is;
    }
    
    
    
    int sum(const Triangular &trian)
    {
        if(!trian.length())
            return 0;
        int val,sum = 0;
        trian.next_reset();
        while(trian.next(val))
            sum+=val;
        return sum;
    }
    
    //Page 113
    int proc1()
    {
        Triangular tri(4);
        cout<<tri<<"-sum of elements:"
            <<sum(tri)<<endl;
        Triangular tri2(4,3);
        cout<<tri2<<"-sum of elements:"
            <<sum(tri2)<<endl;
        Triangular tri3(4,8);
        cout<<tri3<<"-sum of elements:"
            <<sum(tri3)<<endl;
        return 1;
    }
    
    //Page 117
    int proc2()
    {
        char ch;
        bool more = true;
        while (more)
        {
            cout<<"Enter value:";
            int ival;
            cin>>ival;
            bool is_elem = Triangular::is_elem(ival);
            cout<<ival<<(is_elem?" is ":" is not ")
                <<"an element in the Triangular series.\n"
                <<"Another value?[y/n]";
            cin>>ch;
            if(ch=='n'||ch=='N')
                more = false;
        }
        return 1;
    }
    
    //Page 125
    int proc3()
    {
        Triangular tri(20,12);
        Triangular::iterator it = tri.begin();
        Triangular::iterator end_it = tri.end();
        cout<<"Triangular Series of "<<tri.length()<<" elements\n";
        cout<<tri<<endl;
        while(it!=end_it)
        {
            cout<<*it<<' ';
            ++it;
        }
        cout<<endl;
        return 1;
    }
    
    //Page 129
    int proc4()
    {
        Triangular tri(6,3);
        cout<<tri<<'\n';
    
        Triangular tri2;
        cin>>tri2;
        cout<<tri2;
        return 1;
    }
    
    int main()
    {
        int select;
        string notice= "Please input the number for a test\n \
    a non-number input for quit.\n \
    1.Page 113\t2.Page 117\t3.Page 125\t4.Page 129\n";
        cout<<notice;
        cin>>select;
        while(cin)
        {
            switch (select) {
                case 1:
                    proc1();
                    break;
                case 2:
                    proc2();
                    break;
                case 3:
                    proc3();
                    break;
                case 4:
                    proc4();
                    break;
                default:
                    cout<<"undefined num.";
            }
            cout<<notice;
            cin>>select;
        }
    }

     7.习题4.5要求重载一些运算符。怎么安排这些函数的位置呢?可参考:http://blog.csdn.net/insistgogo/article/details/6626952

    第五章

    1.面向对象编程风格的独特概念:继承(P135)、多态(P137)、动态绑定(P137)

    2.P142~145展示了不使用面向对象的继承实现的多态,这种多态是可以用C的struct实现的,不过实现过程和后续维护十分麻烦。

    3.抽象基类的三步设计:子类共通行为、找出哪些是与与型别相依的操作、找出每个操作的存取层级。(P145~146)

    4.一旦一个类拥有纯虚函数,那么程序无法为它产生任何对象;析构函数最好不要声明为纯虚函数。(P147)

    5.派生类用来覆写基类同名函数必须类型、参数、修饰符(是否为const)完全吻合才能在调用时使用,否则仍然使用基类函数(P161~162)。例外:如果基类的虚拟函数返回某个基类形式(通常为pointer或reference)时,派生类的同名函数便可返回基类的派生类的型别(P162)。

    6.在单一对象中展现多种型别的方式是通过基类的pointer和reference。传值时非基类部分会被切掉。(详细解释参考P163)

    7.类指针的转换方式:static_cast和dynamic_cast(P165)

    第六章

    1.class template使用成员初始化列表初始化比在构造函数体内赋值更好:P173

    2.reference to pointer参数(P177)

    3.常量表达式作为template的参数(P181)

    4.成员模板函数:如名称,在class内部声明的template函数。

    第七章

    1.“异常”是某种对象(P192),只有符合catch指定类型的对象才会被捕捉(P193)。

    2.重抛异常:catch里使用throw(P194)

    3.为了管理函数执行时分配额资源,使其在出现异常时能够回收,C++发明者引入所谓资源管理手法,初始化索取资源应在构造函数中完成,回收由析构函数完成,并且所有局部对象的析构函数都会被调用。(P199)

    4.auto_ptr会自动delelet用过new配置的对象,需要memory头文件(P200)

    5.使用exception基类的指针可以捕捉所有的派生异常类。

  • 相关阅读:
    JavaScript中的闭包(closure)
    JavaScript中的继承与原型链
    一个PHP操作大变量的例子
    深入PHP内核之参数
    django创建一个简单的web站点
    django通过添加session来保存公共变量
    第一次登录mysql,使用任何命令都报错ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.
    django搭建的站点,通过localhost能访问,但是通过ip不能访问
    django models实际操作中遇到的一些问题
    python3 django连接mysql,同步表结构
  • 原文地址:https://www.cnblogs.com/wuyuegb2312/p/3023353.html
Copyright © 2020-2023  润新知