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基类的指针可以捕捉所有的派生异常类。

posted @ 2013-04-21 14:33  五岳  阅读(613)  评论(0编辑  收藏  举报
回到顶部