本文主要是《C++编程思想》第一卷的读书笔记,也是对C++基础知识的一个复习。不写很基础的,记录一些自己以前没有注意的知识点。
1、对象的演化
C++的面向对象特性主要体现在对象、继承和多态上。对象就是对特性和行为进行封装。(将变量和方法整合在一起)。继承是类型之间的关系。多态使用晚绑定来实现。
晚绑定的意思就是说执行期才确定所调用的函数的准确地址,是动态多态性。引发多态最关键的一点就是使用基类指针去寻找派生类的地址,去调用派生类的函数。它的特点就是以时间换空间,以效率为代价来换取代码的简洁。实现:典型的编译器对每个包含虚函数的类创建一个称为VTABLE的表。在VTABLE中,编译器放置特定类的虚函数的地址。每个带有虚函数的类,编译器秘密的放置一个指针,称为vpointer,指向这个对象的VTABLE。当通过基类指针做虚函数调用时,编译器静态的插入能取得这个VPTR并在VTABLE表中查找函数地址的代码,这样就能调用正确的函数并引起晚捆绑的发生。
2、数据抽象
声明与定义
声明向计算机介绍名字,定义为名字分配存储空间。声明变量需要使用extern关键字;函数声明的时候可以不加参数名,只给参数类型。头文件就是用来存放声明的。
3、隐藏实现
这一节主要是讲控制外部对内部成员的存取,即public、private、protected。
它们的用处在于:(1)避开用户不需要的工具(2)设计者可以改变内部实现而不会对用户产生影响。
public内外部皆可访问,private只有内部成员函数可以方位,protected除private性质之外继承结构也可以访问而private不行。
友元是显示的声明可以访问内部成员。必须在类内声明。
Class和Struct基本相同,只是Class默认成员是私有的,而Struct是公有的。
4、初始化与清除
本节主要是和构造与析构函数相关。而两者都是从安全性的角度来考虑的。
用构造函数来确保初始化,没有返回值,与返回void是不同的。用析构函数确保清除,
5、函数重载与缺省参数
需要函数重载的原因:重用接口;构造函数。
只能通过作用范围和参数(类型/顺序/个数)来重载,不能用返回值来重载。编译器在编译时会根据这些信息重新生成内部名字。
缺省参数的规则:只有参数列表的后部参数才可以缺省,就是说缺省参数后面不能有非缺省参数。
6、常量
(1)用于值替代
C中#define的升级版,不仅可以值替代,还可以保证不被修改。
const用于集合,const int i[]={1,2,3,4};float f[i[3]];//ilegall
i[3]并不是一个常量表达式,整个才叫作常量表达式。但是你不能i[3]=2这样赋值,因为这样做,你就改变了整个作为一个常量。
(2)const与指针
-->const int *x和int const *x是一样的,都代表一个指向const int的指针。
-->使指针本身变为一个const,
int d = 1; int *const x = &d;
x的指向不能改变,但是x指向的值是可以改变的。
可以把一个非const对象的地址赋给一个const指针,但是不能把一个const对象的地址赋给一个非const指针。
(3)const用在函数参数和返回值
用作参数表示变量初值不会被改变。修饰返回值就表示这个返回值不能被改变。
7、内联函数
目的是减少函数调用过程中产生的开销。
函数体如果过大就会造成冗余。
编译过程中检查类型和调用是否正确,然后直接替换。
8、命名控制
本节主要介绍命名空间以及static的使用
名字空间
namespace 把一个全局的名字空间分成多个可管理的小空间。
和class struct union enum 的区别是:
(1)namespace 只能在全局范畴定义,之间可以互相嵌套;
(2)namespace 定义结尾的大括后右边不必跟一个分号;
(3)namespace 可以在多个头文件中用一个标识符。
每个未编译单元中都可以有一个没有名字的命名空间。
静态成员
类中的static成员会有一个单独的存储空间,静态数据属于类。
(1)静态成员必须在类内声明,在类外定义。
(2)静态成员函数只能访问静态数据成员,也只能调用其他静态成员函数,因为静态成员函数没有this指针。
9、引用和拷贝构造函数
引用是支持C++运算符重载的基础,也为函数参数传入传出提供了便利。
当创建一个引用时必须初始化指向一个存在的对象,不能改变为对另外一个对象的引用。
int& b = a; b和a就都指向了同一个地址。
void f(int&) { }
void g(const int&){}
void main()
{
int a =1;
f(a); //OK
f(1); //error!
g(a); //OK
g(1); //OK
}
拷贝构造函数
X(X&)
编译器会缺省的创建拷贝构造函数,通过将拷贝构造函数声明为私有的可以避免对象的传值调用。
10、运算符重载
语法
考虑两个因素:(1)是一元的还是二元的(2)是作为全局函数还是类的成员函数
作为成员函数时,一元的函数没有参数,二元的有一个参数;全局函数则是1个,两个。
const int& operater+ (int & a){}
11、动态对象创建
C++存在三种区域:静态存储区域(在整个程序运行期间都存在),栈(从{到}存在),堆(动态分配)
针对数组的情况,foo * fp = new foo[100]; delete []fp; 这时,delete fp 只会释放第一个元素。
12、继承和组合
简单的创建一个包含已存在的类的新类称为组合。继承和组合都是为了代码重用。
public继承将保持原访问权限,否则就都是private。
构造函数和析构函数的顺序:构造在类层次的根处开始,首先调用基类的构造函数。析构函数相反。
13、多态和虚函数
多态是面向对象程序继数据抽象和继承之后的第三个基本特征。
虚函数
晚捆绑只对virtual关键字起作用