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,并对它重载了*、++等运算符。这些内容体现在下面的代码中,大部分是按照原书正文写的,小部分是按照原书提供的源码补充的。
/* * ===================================================================================== * 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基类的指针可以捕捉所有的派生异常类。
作者:五岳
出处:http://www.cnblogs.com/wuyuegb2312
对于标题未标注为“转载”的文章均为原创,其版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。