>> C++中,结构是用关键字struct声明的类,默认情况下其成员是公共(public)的。
>> 而C++中,默认情况下类(class)定义中的成员是private的。
>> ∷叫作用域区分符,指明一个函数属于哪个类或一个数据属于哪个类。∷可以不跟类名,表示全局数据或全局函数(即非成员函数)。
>> 在类中定义的成员函数一般规模都比较小,语句只有1~5句,控制结构简单。它们一般为内联函数,即使没有明确用inline标示。
>> 在C++中,类定义通常在头文件中,因此这些成员函数定义也伴随着进入头文件。我们知道函数声明一般在头文件,而函数定义不能在头文件,因为伴随着在不同程序文件中的包含展开,它们将被编译多次。如果是内联函数,包含在头文件中是允许的,因为内联函数作为全局静态属性在源程序中原地扩展。由于在类中定义的成员被默认为内联函数,所以就避免了不能被包含在头文件中的问题。
>> 将类定义和其成员函数定义分开,是目前开发程序的通常做法。我们把类定义(头文件)看成类的外部接口,类的成员函数定义看成类的内部实现。将类拿来编制应用程序时,只需类的外部接口(头文件)。这和我们使用标准库函数的道理是一样的,即只需包含某函数声明的头文件。因为类定义中全部包含了类中成员函数的声明。
>> 在类定义的外部定义成员函数,比在类内部定义时,成员函数名前多加上一个类名。如果该函数的前面没有用“类名∷”表达形式把它与该类紧紧连在一起,编译器就会认为该函数是一个普通函数,它只是与类中的成员函数有相同的名字罢了。以后在连接时,会查出缺少与成员函数相对应的定义而报错。
>> 一个类对象所占据的内存空间由它的数据成员所占据的空间总和所决定。类的成员函数不占据对象的内存空间。
>> 在函数中定义的类称为局部类,局部类在面向对象程序设计中并不多见。类作为类型也有作用域,局部类的作用域在定义该类的函数块中。
局部类的成员函数必须在类定义内部定义,因为若在类外部和包含该类的函数内部中定义,则导致在函数内部定义函数的矛盾。如果在包含类的函数外部定义,则该局部类无法与其取得联系。
◆ 第12章 构造函数
>> 常量和引用变量的初始化必须放在构造函数正在建立数据成员结构空间的时候,也就是放在构造函数的冒号后面。
>> 对于类的数据成员是一般变量的情况,则放在冒号后面与放在函数体中初始化都一样。
◆ 第14章 堆与拷贝构造函数
>> 在C++中,堆分配的概念得到了扩展,不仅C++的关键字new和delete可以分配和释放堆空间,而且通过new建立的对象要调用构造函数,通过delete删除对象也要调用析构函数。
>> C++程序的内存格局通常分为4个区:
(1)全局数据区(data area);
(2)代码区(code area);
(3)堆区(即自由存储区)(heap area);
(4)栈区(stack area)。
全局变量、静态数据、常量及字面量存放在全局数据区,所有类成员函数和非成员函数代码存放在代码区,为运行函数而分配的局部变量、函数参数、返回数据、返回地址等存放在栈区,余下的空间都被作为堆区。
>> 从堆上分配对象数组,只能调用默认的构造函数,不能调用其他任何构造函数。如果该类没有默认构造函数,则不能分配对象数组。
>> delete[]pS中的[]是要告诉C++,该指针指向的是一个数组。如果在[]中填上了数组的长度信息,C++编译系统将忽略,并把它作为[]对待。但如果忘了写[],则程序将会产生运行错误。
>> 一般来说,堆空间相对其他内存空间比较空闲,随要随拿,给程序运行带来了较大的自由度。使用堆空间往往由于:
(1)直到运行时才能知道需要多少对象空间;
(2)不知道对象的生存期到底有多长;
(3)直到运行时才知道一个对象需要多少内存空间。
>> 如果你的类需要析构函数来析构资源,则它也需要一个拷贝构造函数。因为通常对象是自动被析构的。如果需要一个自定义的析构函数,那就意味着有额外资源要在对象被析构之前释放。此时,对象的拷贝就不是浅拷贝了。
◆ 第15章 静态成员与友元
>> 静态成员函数与非静态成员函数的根本区别是什么?
它们的根本区别在于静态成员函数没有this指针,而非静态成员函数有一个指向当前对象的指针this。
>> 在类里声明一个普通函数,标上关键字friend,就成了该类的友元,可以访问该类的一切成员。
>> 友元函数不是成员函数,它是类的朋友,因而能够访问类的全部成员。在类的内部,只能声明它的函数原型,加上friend关键字。友元声明的位置可在类内部的任何位置,既可在public区,也可在protected区,意义完全一样。友元函数定义则在类的外部,一般与类的成员函数定义放在一起。因为类重用时,一般友元是一起提供的。
>> 一个类的成员函数可以是另一个类的友元。
>> 整个类可以是另一个类的友元
◆ 第16章 继承
>> 派生类的析构函数以构造函数相反的顺序被调用
>> 类有公有、保护和私有3种访问权限。当一个类作为基类时,对于使用基类的应用编程,其在类作用域之外,只能访问基类的公有成员,不能访问基类的保护成员和私有成员;对于公有继承基类的类编程,其在派生类作用域中,只能访问基类的公有成员和保护成员,不能访问基类的私有成员。这便是保护成员与私有成员的区别。也即保护成员和私有成员对于应用编程来说,无任何差别;对于类编程,则保护成员对派生类网开一面,保护成员专为继承而设。
◆ 第17章 多态
>> 这种在运行时,能依据其类型确认调用哪个函数的能力,称为多态性,或称迟后联编(late binding),也有的译为滞后联编。
编译时就能确定哪个重载函数被调用的,称为先期联编(early binding)。
>> 若语言不支持多态,则不能被称为面向对象的语言。只支持类而不支持多态,只能称其为基于对象的语言。
>> 为了指明某个成员函数具有多态性,用关键字virtual来标志其为虚函数。
>> 编译通常是在先期联编状态下工作的,只有看见虚函数,才把它作为迟后联编来实现。多态性增加了一些数据存储和执行指令的代价,但与所得到的编程灵活性和方便性相比,还是值得的。
>> 有一种例外,如果基类中的虚函数返回一个基类指针或返回一个基类的引用,子类中的虚函数返回一个子类的指针或子类的引用,则C++将其视为同名虚函数并进行迟后联编。
>> 一个类中将所有的成员函数都尽可能地设置为虚函数对编程固然方便,Java语言中正是这样做的,但是会增加一些时空上的开销。C++是在性能上有偏激追求的编程语言,只选择设置个别成员函数为虚函数。
>> 一个程序员努力工作,写出比较巧妙的代码,以达到减少一些程序行的目的,是不值得的。这种巧妙常常会弄巧成拙。但是通过继承而分解出多余部分,可以合理地减少编程的工作量。
>> C++是强类型语言。当访问一个成员函数时,C++坚持要证明该成员函数在类中存在,否则拒绝接受。
◆ 第18章 运算符重载
>> 作为成员的运算符比之作为非成员的运算符,在声明和定义时,形式上少一个参数。这是由于C++对所有的成员函数隐藏了第一个参数this
>> C++规定:=、()、[]、->这4种运算符必须为成员形式。
>> C++约定,在增量运算符定义中,放上一个整数形参,就是后增量运算符。
◆ 第19章 I/O
>> 写到cerr上的信息是不能被重定向的,它只能输出到屏幕。
>> “cin.getline();”与“cin≫str;”的一个不同是,前者输入一行,行中可以包含空格,后者却以空格或回车作为字串结束,不包含空格。