第3章 隐藏实现
一、C++的存取控制
public 意味着在其后声明的所有成员对所有的人都可以存取。public成员就如同一般的struct成员。private关键字则意味着,除了该类型的创建者和类的内部成员函数之外,任何人都不能存取这些成员。private在设计者与用户之间筑起了一道墙。如果有人试图存取一个私有成员,就会产生一个编译错误。protected与private基本相似,只有一点不同:继承的结构可以访问protected成员,但不能访问private 成员。
二、提前引用某个类时一个值得注意的地方:解决的办法是:注意到Y :: f(X*)引用了一个X 对象的地址。这一点很关键,因为编译器知道如何传递一个地址,这一地址大小是一定的,而不管被传递的对象类型大小。如果试图传递整个对象,编译器就必须知道X 的全部定义以确定它的大小以及如何传递它,这就使程序员无法声明一个类似于Y :: g(X)的函数。
三、句柄类(参见Effective C++,CSDN问题http://www.csdn.net/expert/topic/576/576745.xml?temp=.1663324)
在我们的编程环境中,当一个文件被修改,或它所依赖的文件包含的头文件被修改时,项目负责人需要重复编译这些文件。这意味着无论何时程序员修改了一个类,无论是修改公共的接口部分,还是私有的实现部分,他都得再次编译包含头文件的所有文件。对于一个大的项目而言,在开发初期这可能非常难以处理,因为实现部分可能需要经常改动;如果这个项目非常大,用于编译的时间过多就可能妨碍项目的完成。解决这个问题的技术有时叫句柄类(handle classes )或叫“Cheshire Cat ”[ 1 ]。有关实现的任何东西都消失了,只剩一个单一的指针“smile ”。该指针指向一个结构,该结构的定义与其所有的成员函数的定义一样出现在实现文件中。这样,只要接口部分不改变,头文件就不需变动。而实现部分可以按需要任意更动,完成后只要对实现文件进行重新编译,然后再连接到项目中。这里有个说明这一技术的简单例子。头文件中只包含公共的接口和一个简单的没有完全指定的类指针。
第4章 初始化与清除
一、空间分配
编译器更可能像C 编译器一样,在一个程序块的开头就分配所有的内存。这些对我们来说是无关紧要的,因为作为一个程序员,我们在变量定义之前总是无法得到存储空间。即使存储空间在块的一开始就被分配,构造函数也仍然要到对象的定义时才会被调用,因为标识符只有到此时才有效。这里的意思:内存空间的分配是在程序段的开头就分配,但是程序员的使用必须要等到看到这个标识符被声明时才可以,也只有到了这时他的构造函数才被调用!
第5章 函数重载与缺省参数
一、 缺省函数:在使用缺省参数时必须记住两条规则。第一,只有参数列表的后部参数才可是缺省的,也就是说,我们不可以在一个缺省参数后面又跟一个非缺省的参数。第二,一旦我们开始使用缺省参数,那么这个参数后面的所有参数都必须是缺省的。
二、占位符
多数编译器会给出一条警告信息,并认为我们犯了一个逻辑错误。用这种没有名字的参数就可以防止这种警告产生。更重要的是,如果我们开始用了一个函数参数,而后来发现不需要用它,我们可以高效地将它去掉而不会产生警告错误,而且不需要改动那些调用该函数以前版本的程序代码。
第6章 输入输出流介绍
一、操纵算子
一个称作e n d l 的操纵算子。一个操纵算子作用于流上,这种情况下,插入一新行并清空流(消除所有存储在内部流缓冲区里的还没有输出的字)。也可以只清空流: ccout<<flush;另外有一个基本的操纵算子把基数变为o c t (八进制),d e c (十进制)或h e x (十六进制):cout<<hex<<"0x" <<i<<endl;有一个用于提取的操纵算子“跳过”空格:cin>>ws;
二、输入输出流
一个输入流(istream)或一个输出流(ostream)。有不同类型的输入流和输出流:文件输入流( ifstreams)和文件输出流( ofstreams)、char*内存的(内核格式化)输入流istrstreams和输出流(ostrstreams)、以及与标准C + +串(string)类接口的串输入流(istringstreams)和串输出流(ostringstreams)。
三、面向行的输入get,getline,read,write
有两种选择:成员函数get()或getline()。两个函数都有三个参数:指向存储结果字符的缓冲区指针、缓冲区大小(不能超过其限度)和知道什么时候停止读输入的终止符。终止符有一个经常用到的缺省值"\n"。两个函数遇到输入终止符时,都把零储存在结果加在缓冲区后面。差别虽小但极其重要:get()遇到输入流的分隔符时就停止,而不从输入流中提取分隔符。如果用同样的分隔符再调用一次get()函数,它会立即返回而不带任何输入。(要么在下一个get()说明里用一个不同的分隔符,要么用一个不同的输入函数)。getline()与其相反,它从输入流中提取分隔符,但仍没有把它储存在结果缓冲区里。
读原始字节: 如果想确切知道正在处理什么,并把字节直接移进内存中的变量、数组或结构中,可以用read()函数。第一个参数是一个指向内存目的地址的指针,第二个参数指明要读的字节数。预先将信息存储在一个文件里特别有用。
四、输入输出流缓冲(rdbuf--区的StreamBuf指针)
每一个输入输出流都包含一个指针,指向某种StreamBuf(这依赖于它是否处理标准I / O 、文件、内存等等)。我们可以直接访问StreamBuf。例如,可以向StreamBuf移进、移出原始字节,而不必通过输入输出流来格式化它们。为了允许我们访问StreamBuf,每个流对象有一个叫做Rebuf()的成员函数,这个函数返回指向对象的StreamBuf的指针。这样,我们可以为下层的StreamBuf调用任何成员函数。StreamBuf指针所做的最有兴趣的事之一是:使用“< <”操作符将其与另一个输入输出流联结。这使我们的对象中的所有字节流进“< <”左边的对象中。这意味着,如果把一个输入输出流的所有字节移到另一个输入输出流,我们不必做读入它们的一个字节或一行这样单调的工作。这是一流的方法。
五、在输入输出流中查找(tellg,tellp,seekg,seekp)
在某些情况下,可能需要移动这个流的位置,可以用两种方式处理:第一种方式是在流里绝对定位,叫流定位(StreamBuf);第二种方式像标准C 库函数fseek( )那样做,从文件的开始、结尾或当前位置移动给定数目的字节。
六、建立读/写文件
下面的代码首先建立一个有标志的ifstream,它既是一个输入文件又是一个输出文件,编译器不会让我们向ifstream写,因此,需要建立具有基本流缓冲区的输出流(ostream).这里应该注意的是:ifstream和ostream必须建立起一个关联! 然后对ostream的改变也就会改变到ifstream. ifstream in("in.txt",ios::in|ios::out); ostream out(in.rdbuf());